mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03:00 
			
		
		
		
	(broken state) WIP on tuntap
This commit is contained in:
		
							parent
							
								
									f1c37f8440
								
							
						
					
					
						commit
						0cff56fcc1
					
				
					 6 changed files with 524 additions and 547 deletions
				
			
		| 
						 | 
					@ -112,3 +112,35 @@ func SubnetForKey(publicKey ed25519.PublicKey) *Subnet {
 | 
				
			||||||
	snet[len(prefix)-1] |= 0x01
 | 
						snet[len(prefix)-1] |= 0x01
 | 
				
			||||||
	return &snet
 | 
						return &snet
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetKet returns the partial ed25519.PublicKey for the Address.
 | 
				
			||||||
 | 
					// This is used for key lookup.
 | 
				
			||||||
 | 
					func (a *Address) GetKey() ed25519.PublicKey {
 | 
				
			||||||
 | 
						var key [ed25519.PublicKeySize]byte
 | 
				
			||||||
 | 
						prefix := GetPrefix()
 | 
				
			||||||
 | 
						ones := int(a[len(prefix)])
 | 
				
			||||||
 | 
						for idx := 0; idx < ones; idx++ {
 | 
				
			||||||
 | 
							key[idx/8] |= 0x80 >> byte(idx%8)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						keyOffset := ones + 1
 | 
				
			||||||
 | 
						addrOffset := 8*len(prefix) + 8
 | 
				
			||||||
 | 
						for idx := addrOffset; idx < 8*len(a); idx++ {
 | 
				
			||||||
 | 
							bits := a[idx/8] & (0x80 >> byte(idx%8))
 | 
				
			||||||
 | 
							bits <<= byte(idx % 8)
 | 
				
			||||||
 | 
							keyIdx := keyOffset + (idx - addrOffset)
 | 
				
			||||||
 | 
							bits >>= byte(keyIdx % 8)
 | 
				
			||||||
 | 
							key[keyIdx/8] |= bits
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for idx := range key {
 | 
				
			||||||
 | 
							key[idx] = ^key[idx]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ed25519.PublicKey(key[:])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetKet returns the partial ed25519.PublicKey for the Subnet.
 | 
				
			||||||
 | 
					// This is used for key lookup.
 | 
				
			||||||
 | 
					func (s *Subnet) GetKey() ed25519.PublicKey {
 | 
				
			||||||
 | 
						var addr Address
 | 
				
			||||||
 | 
						copy(addr[:], s[:])
 | 
				
			||||||
 | 
						return addr.GetKey()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,24 +1,24 @@
 | 
				
			||||||
package admin
 | 
					package admin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/hex"
 | 
						//"encoding/hex"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"strconv"
 | 
						//"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gologme/log"
 | 
						"github.com/gologme/log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
						//"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
						//"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
						//"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/version"
 | 
						//"github.com/yggdrasil-network/yggdrasil-go/src/version"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,13 +82,14 @@ func (a *AdminSocket) UpdateConfig(config *config.NodeConfig) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (a *AdminSocket) SetupAdminHandlers(na *AdminSocket) {
 | 
					func (a *AdminSocket) SetupAdminHandlers(na *AdminSocket) {
 | 
				
			||||||
 | 
						/* TODO
 | 
				
			||||||
	a.AddHandler("getSelf", []string{}, func(in Info) (Info, error) {
 | 
						a.AddHandler("getSelf", []string{}, func(in Info) (Info, error) {
 | 
				
			||||||
		ip := a.core.Address().String()
 | 
							ip := a.core.Address().String()
 | 
				
			||||||
		subnet := a.core.Subnet()
 | 
							subnet := a.core.Subnet()
 | 
				
			||||||
		return Info{
 | 
							return Info{
 | 
				
			||||||
			"self": Info{
 | 
								"self": Info{
 | 
				
			||||||
				ip: Info{
 | 
									ip: Info{
 | 
				
			||||||
					"box_pub_key":   a.core.EncryptionPublicKey(),
 | 
										// TODO"box_pub_key":   a.core.EncryptionPublicKey(),
 | 
				
			||||||
					"build_name":    version.BuildName(),
 | 
										"build_name":    version.BuildName(),
 | 
				
			||||||
					"build_version": version.BuildVersion(),
 | 
										"build_version": version.BuildVersion(),
 | 
				
			||||||
					"coords":        fmt.Sprintf("%v", a.core.Coords()),
 | 
										"coords":        fmt.Sprintf("%v", a.core.Coords()),
 | 
				
			||||||
| 
						 | 
					@ -140,6 +141,7 @@ func (a *AdminSocket) SetupAdminHandlers(na *AdminSocket) {
 | 
				
			||||||
			return Info{"switchqueues": queues.asMap()}, nil
 | 
								return Info{"switchqueues": queues.asMap()}, nil
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	*/
 | 
						*/
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
		a.AddHandler("getDHT", []string{}, func(in Info) (Info, error) {
 | 
							a.AddHandler("getDHT", []string{}, func(in Info) (Info, error) {
 | 
				
			||||||
			dht := make(Info)
 | 
								dht := make(Info)
 | 
				
			||||||
			for _, d := range a.core.GetDHT() {
 | 
								for _, d := range a.core.GetDHT() {
 | 
				
			||||||
| 
						 | 
					@ -337,6 +339,7 @@ func (a *AdminSocket) SetupAdminHandlers(na *AdminSocket) {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return Info{}, err
 | 
								return Info{}, err
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Start runs the admin API socket to listen for / respond to admin API calls.
 | 
					// Start runs the admin API socket to listen for / respond to admin API calls.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,227 +0,0 @@
 | 
				
			||||||
package tuntap
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/Arceliar/phony"
 | 
					 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
					 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
					 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
					 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
 | 
					 | 
				
			||||||
	"golang.org/x/net/icmp"
 | 
					 | 
				
			||||||
	"golang.org/x/net/ipv6"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const tunConnTimeout = 2 * time.Minute
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type tunConn struct {
 | 
					 | 
				
			||||||
	phony.Inbox
 | 
					 | 
				
			||||||
	tun   *TunAdapter
 | 
					 | 
				
			||||||
	conn  *yggdrasil.Conn
 | 
					 | 
				
			||||||
	addr  address.Address
 | 
					 | 
				
			||||||
	snet  address.Subnet
 | 
					 | 
				
			||||||
	stop  chan struct{}
 | 
					 | 
				
			||||||
	alive *time.Timer // From calling time.AfterFunc
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *tunConn) close() {
 | 
					 | 
				
			||||||
	s.tun.Act(s, s._close_from_tun)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *tunConn) _close_from_tun() {
 | 
					 | 
				
			||||||
	go s.conn.Close() // Just in case it blocks on actor operations
 | 
					 | 
				
			||||||
	delete(s.tun.addrToConn, s.addr)
 | 
					 | 
				
			||||||
	delete(s.tun.subnetToConn, s.snet)
 | 
					 | 
				
			||||||
	func() {
 | 
					 | 
				
			||||||
		defer func() { recover() }()
 | 
					 | 
				
			||||||
		close(s.stop) // Closes reader/writer goroutines
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *tunConn) _read(bs []byte) (err error) {
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	case <-s.stop:
 | 
					 | 
				
			||||||
		err = errors.New("session was already closed")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(bs) == 0 {
 | 
					 | 
				
			||||||
		err = errors.New("read packet with 0 size")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ipv4 := len(bs) > 20 && bs[0]&0xf0 == 0x40
 | 
					 | 
				
			||||||
	ipv6 := len(bs) > 40 && bs[0]&0xf0 == 0x60
 | 
					 | 
				
			||||||
	isCGA := true
 | 
					 | 
				
			||||||
	// Check source addresses
 | 
					 | 
				
			||||||
	switch {
 | 
					 | 
				
			||||||
	case ipv6 && bs[8] == 0x02 && bytes.Equal(s.addr[:16], bs[8:24]): // source
 | 
					 | 
				
			||||||
	case ipv6 && bs[8] == 0x03 && bytes.Equal(s.snet[:8], bs[8:16]): // source
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		isCGA = false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Check destination addresses
 | 
					 | 
				
			||||||
	switch {
 | 
					 | 
				
			||||||
	case ipv6 && bs[24] == 0x02 && bytes.Equal(s.tun.addr[:16], bs[24:40]): // destination
 | 
					 | 
				
			||||||
	case ipv6 && bs[24] == 0x03 && bytes.Equal(s.tun.subnet[:8], bs[24:32]): // destination
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		isCGA = false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Decide how to handle the packet
 | 
					 | 
				
			||||||
	var skip bool
 | 
					 | 
				
			||||||
	switch {
 | 
					 | 
				
			||||||
	case isCGA: // Allowed
 | 
					 | 
				
			||||||
	case s.tun.ckr.isEnabled() && (ipv4 || ipv6):
 | 
					 | 
				
			||||||
		var srcAddr address.Address
 | 
					 | 
				
			||||||
		var dstAddr address.Address
 | 
					 | 
				
			||||||
		var addrlen int
 | 
					 | 
				
			||||||
		if ipv4 {
 | 
					 | 
				
			||||||
			copy(srcAddr[:], bs[12:16])
 | 
					 | 
				
			||||||
			copy(dstAddr[:], bs[16:20])
 | 
					 | 
				
			||||||
			addrlen = 4
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if ipv6 {
 | 
					 | 
				
			||||||
			copy(srcAddr[:], bs[8:24])
 | 
					 | 
				
			||||||
			copy(dstAddr[:], bs[24:40])
 | 
					 | 
				
			||||||
			addrlen = 16
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if !s.tun.ckr.isValidLocalAddress(dstAddr, addrlen) {
 | 
					 | 
				
			||||||
			// The destination address isn't in our CKR allowed range
 | 
					 | 
				
			||||||
			skip = true
 | 
					 | 
				
			||||||
		} else if key, err := s.tun.ckr.getPublicKeyForAddress(srcAddr, addrlen); err == nil {
 | 
					 | 
				
			||||||
			if *s.conn.RemoteAddr().(*crypto.BoxPubKey) == key {
 | 
					 | 
				
			||||||
				// This is the one allowed CKR case, where source and destination addresses are both good
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				// The CKR key associated with this address doesn't match the sender's NodeID
 | 
					 | 
				
			||||||
				skip = true
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			// We have no CKR route for this source address
 | 
					 | 
				
			||||||
			skip = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		skip = true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if skip {
 | 
					 | 
				
			||||||
		err = errors.New("address not allowed")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	s.tun.writer.writeFrom(s, bs)
 | 
					 | 
				
			||||||
	s.stillAlive()
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *tunConn) writeFrom(from phony.Actor, bs []byte) {
 | 
					 | 
				
			||||||
	s.Act(from, func() {
 | 
					 | 
				
			||||||
		s._write(bs)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *tunConn) _write(bs []byte) (err error) {
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	case <-s.stop:
 | 
					 | 
				
			||||||
		err = errors.New("session was already closed")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	v4 := len(bs) > 20 && bs[0]&0xf0 == 0x40
 | 
					 | 
				
			||||||
	v6 := len(bs) > 40 && bs[0]&0xf0 == 0x60
 | 
					 | 
				
			||||||
	isCGA := true
 | 
					 | 
				
			||||||
	// Check source addresses
 | 
					 | 
				
			||||||
	switch {
 | 
					 | 
				
			||||||
	case v6 && bs[8] == 0x02 && bytes.Equal(s.tun.addr[:16], bs[8:24]): // source
 | 
					 | 
				
			||||||
	case v6 && bs[8] == 0x03 && bytes.Equal(s.tun.subnet[:8], bs[8:16]): // source
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		isCGA = false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Check destiantion addresses
 | 
					 | 
				
			||||||
	switch {
 | 
					 | 
				
			||||||
	case v6 && bs[24] == 0x02 && bytes.Equal(s.addr[:16], bs[24:40]): // destination
 | 
					 | 
				
			||||||
	case v6 && bs[24] == 0x03 && bytes.Equal(s.snet[:8], bs[24:32]): // destination
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		isCGA = false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Decide how to handle the packet
 | 
					 | 
				
			||||||
	var skip bool
 | 
					 | 
				
			||||||
	switch {
 | 
					 | 
				
			||||||
	case isCGA: // Allowed
 | 
					 | 
				
			||||||
	case s.tun.ckr.isEnabled() && (v4 || v6):
 | 
					 | 
				
			||||||
		var srcAddr address.Address
 | 
					 | 
				
			||||||
		var dstAddr address.Address
 | 
					 | 
				
			||||||
		var addrlen int
 | 
					 | 
				
			||||||
		if v4 {
 | 
					 | 
				
			||||||
			copy(srcAddr[:], bs[12:16])
 | 
					 | 
				
			||||||
			copy(dstAddr[:], bs[16:20])
 | 
					 | 
				
			||||||
			addrlen = 4
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if v6 {
 | 
					 | 
				
			||||||
			copy(srcAddr[:], bs[8:24])
 | 
					 | 
				
			||||||
			copy(dstAddr[:], bs[24:40])
 | 
					 | 
				
			||||||
			addrlen = 16
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if !s.tun.ckr.isValidLocalAddress(srcAddr, addrlen) {
 | 
					 | 
				
			||||||
			// The source address isn't in our CKR allowed range
 | 
					 | 
				
			||||||
			skip = true
 | 
					 | 
				
			||||||
		} else if key, err := s.tun.ckr.getPublicKeyForAddress(dstAddr, addrlen); err == nil {
 | 
					 | 
				
			||||||
			if *s.conn.RemoteAddr().(*crypto.BoxPubKey) == key {
 | 
					 | 
				
			||||||
				// This is the one allowed CKR case, where source and destination addresses are both good
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				// The CKR key associated with this address doesn't match the sender's NodeID
 | 
					 | 
				
			||||||
				skip = true
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			// We have no CKR route for this destination address... why do we have the packet in the first place?
 | 
					 | 
				
			||||||
			skip = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		skip = true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if skip {
 | 
					 | 
				
			||||||
		err = errors.New("address not allowed")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	msg := yggdrasil.FlowKeyMessage{
 | 
					 | 
				
			||||||
		FlowKey: util.GetFlowKey(bs),
 | 
					 | 
				
			||||||
		Message: bs,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	s.conn.WriteFrom(s, msg, func(err error) {
 | 
					 | 
				
			||||||
		if err == nil {
 | 
					 | 
				
			||||||
			// No point in wasting resources to send back an error if there was none
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		s.Act(s.conn, func() {
 | 
					 | 
				
			||||||
			if e, eok := err.(yggdrasil.ConnError); !eok {
 | 
					 | 
				
			||||||
				if e.Closed() {
 | 
					 | 
				
			||||||
					s.tun.log.Debugln(s.conn.String(), "TUN/TAP generic write debug:", err)
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					s.tun.log.Errorln(s.conn.String(), "TUN/TAP generic write error:", err)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else if e.PacketTooBig() {
 | 
					 | 
				
			||||||
				// TODO: This currently isn't aware of IPv4 for CKR
 | 
					 | 
				
			||||||
				ptb := &icmp.PacketTooBig{
 | 
					 | 
				
			||||||
					MTU:  int(e.PacketMaximumSize()),
 | 
					 | 
				
			||||||
					Data: bs[:900],
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if packet, err := CreateICMPv6(bs[8:24], bs[24:40], ipv6.ICMPTypePacketTooBig, 0, ptb); err == nil {
 | 
					 | 
				
			||||||
					s.tun.writer.writeFrom(s, packet)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				if e.Closed() {
 | 
					 | 
				
			||||||
					s.tun.log.Debugln(s.conn.String(), "TUN/TAP conn write debug:", err)
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					s.tun.log.Errorln(s.conn.String(), "TUN/TAP conn write error:", err)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	s.stillAlive()
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *tunConn) stillAlive() {
 | 
					 | 
				
			||||||
	if s.alive != nil {
 | 
					 | 
				
			||||||
		s.alive.Stop()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	s.alive = time.AfterFunc(tunConnTimeout, s.close)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,12 @@
 | 
				
			||||||
package tuntap
 | 
					package tuntap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
						//"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
 | 
						//"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/net/icmp"
 | 
						//"golang.org/x/net/icmp"
 | 
				
			||||||
	"golang.org/x/net/ipv6"
 | 
						//"golang.org/x/net/ipv6"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/Arceliar/phony"
 | 
						"github.com/Arceliar/phony"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -84,6 +84,8 @@ func (tun *TunAdapter) handlePacketFrom(from phony.Actor, packet []byte, err err
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// does the work of reading a packet and sending it to the correct tunConn
 | 
					// does the work of reading a packet and sending it to the correct tunConn
 | 
				
			||||||
func (tun *TunAdapter) _handlePacket(recvd []byte, err error) {
 | 
					func (tun *TunAdapter) _handlePacket(recvd []byte, err error) {
 | 
				
			||||||
 | 
						panic("TODO")
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			tun.log.Errorln("TUN iface read error:", err)
 | 
								tun.log.Errorln("TUN iface read error:", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
| 
						 | 
					@ -139,7 +141,7 @@ func (tun *TunAdapter) _handlePacket(recvd []byte, err error) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if tun.ckr.isEnabled() {
 | 
							if tun.ckr.isEnabled() {
 | 
				
			||||||
			if addrlen != 16 || (!dstAddr.IsValid() && !dstSnet.IsValid()) {
 | 
								if addrlen != 16 || (!dstAddr.IsValid() && !dstSnet.IsValid()) {
 | 
				
			||||||
			if /*key*/ _, err := tun.ckr.getPublicKeyForAddress(dstAddr, addrlen); err == nil {
 | 
									if key, err := tun.ckr.getPublicKeyForAddress(dstAddr, addrlen); err == nil {
 | 
				
			||||||
					// A public key was found, get the node ID for the search
 | 
										// A public key was found, get the node ID for the search
 | 
				
			||||||
					panic("TODO")
 | 
										panic("TODO")
 | 
				
			||||||
					//dstNodeID := crypto.GetNodeID(&key)
 | 
										//dstNodeID := crypto.GetNodeID(&key)
 | 
				
			||||||
| 
						 | 
					@ -219,4 +221,5 @@ func (tun *TunAdapter) _handlePacket(recvd []byte, err error) {
 | 
				
			||||||
		if isIn && session != nil {
 | 
							if isIn && session != nil {
 | 
				
			||||||
			session.writeFrom(tun, bs)
 | 
								session.writeFrom(tun, bs)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										152
									
								
								src/tuntap/keystore.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								src/tuntap/keystore.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,152 @@
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
						mtu     MTU         // TODO use this
 | 
				
			||||||
 | 
						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()
 | 
				
			||||||
 | 
						defer k.mutex.Unlock()
 | 
				
			||||||
 | 
						if info := k.addrToInfo[addr]; info != nil {
 | 
				
			||||||
 | 
							k.tun.core.WriteTo(bs, iwt.Addr(info.key[:]))
 | 
				
			||||||
 | 
							k.resetTimeout(info)
 | 
				
			||||||
 | 
						} 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)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (k *keyStore) sendToSubnet(subnet address.Subnet, bs []byte) {
 | 
				
			||||||
 | 
						k.mutex.Lock()
 | 
				
			||||||
 | 
						defer k.mutex.Unlock()
 | 
				
			||||||
 | 
						if info := k.subnetToInfo[subnet]; info != nil {
 | 
				
			||||||
 | 
							k.tun.core.WriteTo(bs, iwt.Addr(info.key[:]))
 | 
				
			||||||
 | 
							k.resetTimeout(info)
 | 
				
			||||||
 | 
						} 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)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (k *keyStore) update(key ed25519.PublicKey) {
 | 
				
			||||||
 | 
						k.mutex.Lock()
 | 
				
			||||||
 | 
						defer k.mutex.Unlock()
 | 
				
			||||||
 | 
						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[:]))
 | 
				
			||||||
 | 
							info.mtu = MTU(^uint16(0)) // TODO
 | 
				
			||||||
 | 
							k.keyToInfo[info.key] = info
 | 
				
			||||||
 | 
							k.addrToInfo[info.address] = info
 | 
				
			||||||
 | 
							k.subnetToInfo[info.subnet] = info
 | 
				
			||||||
 | 
							k.resetTimeout(info)
 | 
				
			||||||
 | 
							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)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						k.resetTimeout(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)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@ package tuntap
 | 
				
			||||||
// TODO: Don't block in reader on writes that are pending searches
 | 
					// TODO: Don't block in reader on writes that are pending searches
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/ed25519"
 | 
				
			||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
| 
						 | 
					@ -38,13 +39,12 @@ const tun_IPv6_HEADER_LENGTH = 40
 | 
				
			||||||
// calling yggdrasil.Start().
 | 
					// calling yggdrasil.Start().
 | 
				
			||||||
type TunAdapter struct {
 | 
					type TunAdapter struct {
 | 
				
			||||||
	core        *yggdrasil.Core
 | 
						core        *yggdrasil.Core
 | 
				
			||||||
 | 
						store       keyStore
 | 
				
			||||||
	writer      tunWriter
 | 
						writer      tunWriter
 | 
				
			||||||
	reader      tunReader
 | 
						reader      tunReader
 | 
				
			||||||
	config      *config.NodeState
 | 
						config      *config.NodeState
 | 
				
			||||||
	log         *log.Logger
 | 
						log         *log.Logger
 | 
				
			||||||
	reconfigure chan chan error
 | 
						reconfigure chan chan error
 | 
				
			||||||
	listener    *yggdrasil.Listener
 | 
					 | 
				
			||||||
	dialer      *yggdrasil.Dialer
 | 
					 | 
				
			||||||
	addr        address.Address
 | 
						addr        address.Address
 | 
				
			||||||
	subnet      address.Subnet
 | 
						subnet      address.Subnet
 | 
				
			||||||
	ckr         cryptokey
 | 
						ckr         cryptokey
 | 
				
			||||||
| 
						 | 
					@ -53,15 +53,12 @@ type TunAdapter struct {
 | 
				
			||||||
	iface       tun.Device
 | 
						iface       tun.Device
 | 
				
			||||||
	phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below
 | 
						phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below
 | 
				
			||||||
	//mutex        sync.RWMutex // Protects the below
 | 
						//mutex        sync.RWMutex // Protects the below
 | 
				
			||||||
	addrToConn   map[address.Address]*tunConn
 | 
					 | 
				
			||||||
	subnetToConn map[address.Subnet]*tunConn
 | 
					 | 
				
			||||||
	dials        map[string][][]byte // Buffer of packets to send after dialing finishes
 | 
					 | 
				
			||||||
	isOpen bool
 | 
						isOpen bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type TunOptions struct {
 | 
					type TunOptions struct {
 | 
				
			||||||
	Listener *yggdrasil.Listener
 | 
						//Listener *yggdrasil.Listener
 | 
				
			||||||
	Dialer   *yggdrasil.Dialer
 | 
						//Dialer   *yggdrasil.Dialer
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Gets the maximum supported MTU for the platform based on the defaults in
 | 
					// Gets the maximum supported MTU for the platform based on the defaults in
 | 
				
			||||||
| 
						 | 
					@ -113,20 +110,20 @@ func MaximumMTU() MTU {
 | 
				
			||||||
// Init initialises the TUN module. You must have acquired a Listener from
 | 
					// Init initialises the TUN module. You must have acquired a Listener from
 | 
				
			||||||
// the Yggdrasil core before this point and it must not be in use elsewhere.
 | 
					// the Yggdrasil core before this point and it must not be in use elsewhere.
 | 
				
			||||||
func (tun *TunAdapter) Init(core *yggdrasil.Core, config *config.NodeState, log *log.Logger, options interface{}) error {
 | 
					func (tun *TunAdapter) Init(core *yggdrasil.Core, config *config.NodeState, log *log.Logger, options interface{}) error {
 | 
				
			||||||
 | 
						/* TODO
 | 
				
			||||||
	tunoptions, ok := options.(TunOptions)
 | 
						tunoptions, ok := options.(TunOptions)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return fmt.Errorf("invalid options supplied to TunAdapter module")
 | 
							return fmt.Errorf("invalid options supplied to TunAdapter module")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						*/
 | 
				
			||||||
	tun.core = core
 | 
						tun.core = core
 | 
				
			||||||
 | 
						tun.store.init(tun)
 | 
				
			||||||
	tun.config = config
 | 
						tun.config = config
 | 
				
			||||||
	tun.log = log
 | 
						tun.log = log
 | 
				
			||||||
	tun.listener = tunoptions.Listener
 | 
					 | 
				
			||||||
	tun.dialer = tunoptions.Dialer
 | 
					 | 
				
			||||||
	tun.addrToConn = make(map[address.Address]*tunConn)
 | 
					 | 
				
			||||||
	tun.subnetToConn = make(map[address.Subnet]*tunConn)
 | 
					 | 
				
			||||||
	tun.dials = make(map[string][][]byte)
 | 
					 | 
				
			||||||
	tun.writer.tun = tun
 | 
						tun.writer.tun = tun
 | 
				
			||||||
	tun.reader.tun = tun
 | 
						tun.reader.tun = tun
 | 
				
			||||||
 | 
						tun.core.SetOutOfBandHandler(tun.oobHandler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,7 +142,7 @@ func (tun *TunAdapter) _start() error {
 | 
				
			||||||
		return errors.New("TUN module is already started")
 | 
							return errors.New("TUN module is already started")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	current := tun.config.GetCurrent()
 | 
						current := tun.config.GetCurrent()
 | 
				
			||||||
	if tun.config == nil || tun.listener == nil || tun.dialer == nil {
 | 
						if tun.config == nil {
 | 
				
			||||||
		return errors.New("no configuration available to TUN")
 | 
							return errors.New("no configuration available to TUN")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var boxPub crypto.BoxPubKey
 | 
						var boxPub crypto.BoxPubKey
 | 
				
			||||||
| 
						 | 
					@ -169,9 +166,9 @@ func (tun *TunAdapter) _start() error {
 | 
				
			||||||
	if tun.MTU() != current.IfMTU {
 | 
						if tun.MTU() != current.IfMTU {
 | 
				
			||||||
		tun.log.Warnf("Warning: Interface MTU %d automatically adjusted to %d (supported range is 1280-%d)", current.IfMTU, tun.MTU(), MaximumMTU())
 | 
							tun.log.Warnf("Warning: Interface MTU %d automatically adjusted to %d (supported range is 1280-%d)", current.IfMTU, tun.MTU(), MaximumMTU())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tun.core.SetMaximumSessionMTU(tun.MTU())
 | 
						// TODO tun.core.SetMaximumSessionMTU(tun.MTU())
 | 
				
			||||||
	tun.isOpen = true
 | 
						tun.isOpen = true
 | 
				
			||||||
	go tun.handler()
 | 
						// TODO go tun.handler()
 | 
				
			||||||
	tun.reader.Act(nil, tun.reader._read) // Start the reader
 | 
						tun.reader.Act(nil, tun.reader._read) // Start the reader
 | 
				
			||||||
	tun.ckr.init(tun)
 | 
						tun.ckr.init(tun)
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
| 
						 | 
					@ -225,6 +222,7 @@ func (tun *TunAdapter) UpdateConfig(config *config.NodeConfig) {
 | 
				
			||||||
	tun.Act(nil, tun.ckr.configure)
 | 
						tun.Act(nil, tun.ckr.configure)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
func (tun *TunAdapter) handler() error {
 | 
					func (tun *TunAdapter) handler() error {
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		// Accept the incoming connection
 | 
							// Accept the incoming connection
 | 
				
			||||||
| 
						 | 
					@ -283,3 +281,19 @@ func (tun *TunAdapter) _wrap(conn *yggdrasil.Conn) (c *tunConn, err error) {
 | 
				
			||||||
	// Return
 | 
						// Return
 | 
				
			||||||
	return c, err
 | 
						return c, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tun *TunAdapter) oobHandler(fromKey, toKey ed25519.PublicKey, data []byte) {
 | 
				
			||||||
 | 
						panic("TODO")
 | 
				
			||||||
 | 
						// parse packet
 | 
				
			||||||
 | 
						// If it's a lookup then send a response
 | 
				
			||||||
 | 
						// If it's a response then (maybe) update the keystore
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tun *TunAdapter) sendKeyLookup(partial ed25519.PublicKey) {
 | 
				
			||||||
 | 
						panic("TODO")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tun *TunAdapter) sendKeyResponse(dest ed25519.PublicKey) {
 | 
				
			||||||
 | 
						panic("TODO")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue