mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-11-23 18:15:24 +00:00
mostly finish migration of IP stuff to core, tuntap is still responsible for ICMP PacketTooBig
This commit is contained in:
parent
1147ee1934
commit
816356ea65
@ -222,3 +222,28 @@ func (c *Core) RemovePeer(addr string, sintf string) error {
|
|||||||
func (c *Core) CallPeer(u *url.URL, sintf string) error {
|
func (c *Core) CallPeer(u *url.URL, sintf string) error {
|
||||||
return c.links.call(u, sintf)
|
return c.links.call(u, sintf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Core) PublicKey() ed25519.PublicKey {
|
||||||
|
return c.public
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) MaxMTU() uint64 {
|
||||||
|
return c.store.maxSessionMTU()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/ed25519"
|
"crypto/ed25519"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
@ -43,13 +44,13 @@ func (c *Core) _init() error {
|
|||||||
// Init sets up structs
|
// Init sets up structs
|
||||||
// Start launches goroutines that depend on structs being set up
|
// Start launches goroutines that depend on structs being set up
|
||||||
// This is pretty much required to completely avoid race conditions
|
// This is pretty much required to completely avoid race conditions
|
||||||
|
c.config.RLock()
|
||||||
|
defer c.config.RUnlock()
|
||||||
if c.log == nil {
|
if c.log == nil {
|
||||||
c.log = log.New(ioutil.Discard, "", 0)
|
c.log = log.New(ioutil.Discard, "", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.config.RLock()
|
|
||||||
sigPriv, err := hex.DecodeString(c.config.PrivateKey)
|
sigPriv, err := hex.DecodeString(c.config.PrivateKey)
|
||||||
c.config.RUnlock()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -65,6 +66,9 @@ func (c *Core) _init() error {
|
|||||||
c.ctx, c.ctxCancel = context.WithCancel(context.Background())
|
c.ctx, c.ctxCancel = context.WithCancel(context.Background())
|
||||||
c.store.init(c)
|
c.store.init(c)
|
||||||
c.proto.init(c)
|
c.proto.init(c)
|
||||||
|
if err := c.proto.nodeinfo.setNodeInfo(c.config.NodeInfo, c.config.NodeInfoPrivacy); err != nil {
|
||||||
|
return fmt.Errorf("setNodeInfo: %w", err)
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,20 +181,3 @@ 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
|
|
||||||
}
|
|
||||||
|
@ -26,7 +26,6 @@ type keyStore struct {
|
|||||||
addrBuffer map[address.Address]*buffer
|
addrBuffer map[address.Address]*buffer
|
||||||
subnetToInfo map[address.Subnet]*keyInfo
|
subnetToInfo map[address.Subnet]*keyInfo
|
||||||
subnetBuffer map[address.Subnet]*buffer
|
subnetBuffer map[address.Subnet]*buffer
|
||||||
buf []byte // scratch space to prefix with typeSessionTraffic before sending
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type keyInfo struct {
|
type keyInfo struct {
|
||||||
@ -45,7 +44,10 @@ func (k *keyStore) init(core *Core) {
|
|||||||
k.core = core
|
k.core = core
|
||||||
k.address = *address.AddrForKey(k.core.public)
|
k.address = *address.AddrForKey(k.core.public)
|
||||||
k.subnet = *address.SubnetForKey(k.core.public)
|
k.subnet = *address.SubnetForKey(k.core.public)
|
||||||
k.core.pc.SetOutOfBandHandler(k.oobHandler)
|
if err := k.core.pc.SetOutOfBandHandler(k.oobHandler); err != nil {
|
||||||
|
err = fmt.Errorf("tun.core.SetOutOfBandHander: %w", err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
k.keyToInfo = make(map[keyArray]*keyInfo)
|
k.keyToInfo = make(map[keyArray]*keyInfo)
|
||||||
k.addrToInfo = make(map[address.Address]*keyInfo)
|
k.addrToInfo = make(map[address.Address]*keyInfo)
|
||||||
k.addrBuffer = make(map[address.Address]*buffer)
|
k.addrBuffer = make(map[address.Address]*buffer)
|
||||||
@ -204,8 +206,9 @@ func (k *keyStore) maxSessionMTU() uint64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (k *keyStore) readPC(p []byte) (int, error) {
|
func (k *keyStore) readPC(p []byte) (int, error) {
|
||||||
|
buf := make([]byte, k.core.pc.MTU(), 65535)
|
||||||
for {
|
for {
|
||||||
bs := p
|
bs := buf
|
||||||
n, from, err := k.core.pc.ReadFrom(bs)
|
n, from, err := k.core.pc.ReadFrom(bs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
@ -235,7 +238,7 @@ func (k *keyStore) readPC(p []byte) (int, error) {
|
|||||||
if len(bs) < 40 {
|
if len(bs) < 40 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
/* TODO ICMP packet too big
|
/* TODO? ICMP packet too big, for now tuntap sends this when needed
|
||||||
if len(bs) > int(tun.MTU()) {
|
if len(bs) > int(tun.MTU()) {
|
||||||
ptb := &icmp.PacketTooBig{
|
ptb := &icmp.PacketTooBig{
|
||||||
MTU: int(tun.mtu),
|
MTU: int(tun.mtu),
|
||||||
@ -282,12 +285,13 @@ func (k *keyStore) writePC(bs []byte) (int, error) {
|
|||||||
if srcAddr != k.address && srcSubnet != k.subnet {
|
if srcAddr != k.address && srcSubnet != k.subnet {
|
||||||
return 0, errors.New("wrong source address")
|
return 0, errors.New("wrong source address")
|
||||||
}
|
}
|
||||||
k.buf = append(k.buf[:0], typeSessionTraffic)
|
buf := make([]byte, 1+len(bs), 65535)
|
||||||
k.buf = append(k.buf, bs...)
|
buf[0] = typeSessionTraffic
|
||||||
|
copy(buf[1:], bs)
|
||||||
if dstAddr.IsValid() {
|
if dstAddr.IsValid() {
|
||||||
k.sendToAddress(dstAddr, k.buf)
|
k.sendToAddress(dstAddr, buf)
|
||||||
} else if dstSubnet.IsValid() {
|
} else if dstSubnet.IsValid() {
|
||||||
k.sendToSubnet(dstSubnet, k.buf)
|
k.sendToSubnet(dstSubnet, buf)
|
||||||
} else {
|
} else {
|
||||||
return 0, errors.New("invalid destination address")
|
return 0, errors.New("invalid destination address")
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,8 @@ func (t *TunAdapter) SetupAdminHandlers(a *admin.AdminSocket) {
|
|||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
})
|
})
|
||||||
_ = a.AddHandler("getNodeInfo", []string{"key"}, t.proto.nodeinfo.nodeInfoAdminHandler)
|
//_ = a.AddHandler("getNodeInfo", []string{"key"}, t.proto.nodeinfo.nodeInfoAdminHandler)
|
||||||
_ = a.AddHandler("debug_remoteGetSelf", []string{"key"}, t.proto.getSelfHandler)
|
//_ = a.AddHandler("debug_remoteGetSelf", []string{"key"}, t.proto.getSelfHandler)
|
||||||
_ = a.AddHandler("debug_remoteGetPeers", []string{"key"}, t.proto.getPeersHandler)
|
//_ = a.AddHandler("debug_remoteGetPeers", []string{"key"}, t.proto.getPeersHandler)
|
||||||
_ = a.AddHandler("debug_remoteGetDHT", []string{"key"}, t.proto.getDHTHandler)
|
//_ = a.AddHandler("debug_remoteGetDHT", []string{"key"}, t.proto.getDHTHandler)
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,8 @@
|
|||||||
package tuntap
|
package tuntap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ed25519"
|
|
||||||
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
|
||||||
"golang.org/x/net/icmp"
|
"golang.org/x/net/icmp"
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
|
|
||||||
//"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
|
||||||
//"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
|
|
||||||
|
|
||||||
//"golang.org/x/net/icmp"
|
|
||||||
//"golang.org/x/net/ipv6"
|
|
||||||
|
|
||||||
iwt "github.com/Arceliar/ironwood/types"
|
|
||||||
//"github.com/Arceliar/phony"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const TUN_OFFSET_BYTES = 4
|
const TUN_OFFSET_BYTES = 4
|
||||||
@ -34,28 +22,8 @@ func (tun *TunAdapter) read() {
|
|||||||
begin := TUN_OFFSET_BYTES
|
begin := TUN_OFFSET_BYTES
|
||||||
end := begin + n
|
end := begin + n
|
||||||
bs := buf[begin:end]
|
bs := buf[begin:end]
|
||||||
if bs[0]&0xf0 != 0x60 {
|
if _, err := tun.core.Write(bs); err != nil {
|
||||||
continue // not IPv6
|
tun.log.Errorln("Unable to send packet:", err)
|
||||||
}
|
|
||||||
if len(bs) < 40 {
|
|
||||||
tun.log.Traceln("TUN iface read undersized ipv6 packet, length:", len(bs))
|
|
||||||
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 srcAddr != tun.addr && srcSubnet != tun.subnet {
|
|
||||||
continue // Wrong source address
|
|
||||||
}
|
|
||||||
bs = buf[begin-1 : end]
|
|
||||||
bs[0] = typeSessionTraffic
|
|
||||||
if dstAddr.IsValid() {
|
|
||||||
tun.store.sendToAddress(dstAddr, bs)
|
|
||||||
} else if dstSubnet.IsValid() {
|
|
||||||
tun.store.sendToSubnet(dstSubnet, bs)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,63 +31,23 @@ func (tun *TunAdapter) read() {
|
|||||||
func (tun *TunAdapter) write() {
|
func (tun *TunAdapter) write() {
|
||||||
var buf [TUN_OFFSET_BYTES + 65535]byte
|
var buf [TUN_OFFSET_BYTES + 65535]byte
|
||||||
for {
|
for {
|
||||||
bs := buf[TUN_OFFSET_BYTES-1:]
|
bs := buf[TUN_OFFSET_BYTES:]
|
||||||
n, from, err := tun.core.ReadFrom(bs)
|
n, err := tun.core.Read(bs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
tun.log.Errorln("Exiting tun writer due to core read error:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if n == 0 {
|
if n > int(tun.MTU()) {
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch bs[0] {
|
|
||||||
case typeSessionTraffic:
|
|
||||||
// This is what we want to handle here
|
|
||||||
if !tun.isEnabled {
|
|
||||||
continue // Drop traffic if the tun is disabled
|
|
||||||
}
|
|
||||||
case typeSessionProto:
|
|
||||||
var key keyArray
|
|
||||||
copy(key[:], from.(iwt.Addr))
|
|
||||||
data := append([]byte(nil), bs[1:n]...)
|
|
||||||
tun.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
|
|
||||||
}
|
|
||||||
if len(bs) > int(tun.MTU()) {
|
|
||||||
ptb := &icmp.PacketTooBig{
|
ptb := &icmp.PacketTooBig{
|
||||||
MTU: int(tun.mtu),
|
MTU: int(tun.mtu),
|
||||||
Data: bs[:40],
|
Data: bs[:40],
|
||||||
}
|
}
|
||||||
if packet, err := CreateICMPv6(bs[8:24], bs[24:40], ipv6.ICMPTypePacketTooBig, 0, ptb); err == nil {
|
if packet, err := CreateICMPv6(bs[8:24], bs[24:40], ipv6.ICMPTypePacketTooBig, 0, ptb); err == nil {
|
||||||
_, _ = tun.core.WriteTo(packet, from)
|
_, _ = tun.core.Write(packet)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var srcAddr, dstAddr address.Address
|
bs = buf[:TUN_OFFSET_BYTES+n]
|
||||||
var srcSubnet, dstSubnet address.Subnet
|
|
||||||
copy(srcAddr[:], bs[8:])
|
|
||||||
copy(dstAddr[:], bs[24:])
|
|
||||||
copy(srcSubnet[:], bs[8:])
|
|
||||||
copy(dstSubnet[:], bs[24:])
|
|
||||||
if dstAddr != tun.addr && dstSubnet != tun.subnet {
|
|
||||||
continue // bad local address/subnet
|
|
||||||
}
|
|
||||||
info := tun.store.update(ed25519.PublicKey(from.(iwt.Addr)))
|
|
||||||
if srcAddr != info.address && srcSubnet != info.subnet {
|
|
||||||
continue // bad remote address/subnet
|
|
||||||
}
|
|
||||||
bs = buf[:TUN_OFFSET_BYTES+len(bs)]
|
|
||||||
if _, err = tun.iface.Write(bs, TUN_OFFSET_BYTES); err != nil {
|
if _, err = tun.iface.Write(bs, TUN_OFFSET_BYTES); err != nil {
|
||||||
tun.Act(nil, func() {
|
tun.Act(nil, func() {
|
||||||
if !tun.isOpen {
|
if !tun.isOpen {
|
||||||
|
@ -9,7 +9,6 @@ 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"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
@ -34,7 +33,6 @@ type MTU uint16
|
|||||||
// calling yggdrasil.Start().
|
// calling yggdrasil.Start().
|
||||||
type TunAdapter struct {
|
type TunAdapter struct {
|
||||||
core *core.Core
|
core *core.Core
|
||||||
store keyStore
|
|
||||||
config *config.NodeConfig
|
config *config.NodeConfig
|
||||||
log *log.Logger
|
log *log.Logger
|
||||||
addr address.Address
|
addr address.Address
|
||||||
@ -45,7 +43,6 @@ type TunAdapter struct {
|
|||||||
//mutex sync.RWMutex // Protects the below
|
//mutex sync.RWMutex // Protects the below
|
||||||
isOpen bool
|
isOpen bool
|
||||||
isEnabled bool // Used by the writer to drop sessionTraffic if not enabled
|
isEnabled bool // Used by the writer to drop sessionTraffic if not enabled
|
||||||
proto protoHandler
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@ -98,18 +95,8 @@ func MaximumMTU() uint64 {
|
|||||||
// 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 *core.Core, config *config.NodeConfig, log *log.Logger, options interface{}) error {
|
func (tun *TunAdapter) Init(core *core.Core, config *config.NodeConfig, log *log.Logger, options interface{}) error {
|
||||||
tun.core = core
|
tun.core = core
|
||||||
tun.store.init(tun)
|
|
||||||
tun.config = config
|
tun.config = config
|
||||||
tun.log = log
|
tun.log = log
|
||||||
tun.proto.init(tun)
|
|
||||||
tun.config.RLock()
|
|
||||||
if err := tun.proto.nodeinfo.setNodeInfo(tun.config.NodeInfo, tun.config.NodeInfoPrivacy); err != nil {
|
|
||||||
return fmt.Errorf("tun.proto.nodeinfo.setNodeInfo: %w", err)
|
|
||||||
}
|
|
||||||
tun.config.RUnlock()
|
|
||||||
if err := tun.core.SetOutOfBandHandler(tun.oobHandler); err != nil {
|
|
||||||
return fmt.Errorf("tun.core.SetOutOfBandHander: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,8 +119,7 @@ func (tun *TunAdapter) _start() error {
|
|||||||
if tun.config == nil {
|
if tun.config == nil {
|
||||||
return errors.New("no configuration available to TUN")
|
return errors.New("no configuration available to TUN")
|
||||||
}
|
}
|
||||||
sk := tun.core.PrivateKey()
|
pk := tun.core.PublicKey()
|
||||||
pk := sk.Public().(ed25519.PublicKey)
|
|
||||||
tun.addr = *address.AddrForKey(pk)
|
tun.addr = *address.AddrForKey(pk)
|
||||||
tun.subnet = *address.SubnetForKey(pk)
|
tun.subnet = *address.SubnetForKey(pk)
|
||||||
addr := fmt.Sprintf("%s/%d", net.IP(tun.addr[:]).String(), 8*len(address.GetPrefix())-1)
|
addr := fmt.Sprintf("%s/%d", net.IP(tun.addr[:]).String(), 8*len(address.GetPrefix())-1)
|
||||||
@ -144,8 +130,8 @@ func (tun *TunAdapter) _start() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
mtu := tun.config.IfMTU
|
mtu := tun.config.IfMTU
|
||||||
if tun.maxSessionMTU() < mtu {
|
if tun.core.MaxMTU() < mtu {
|
||||||
mtu = tun.maxSessionMTU()
|
mtu = tun.core.MaxMTU()
|
||||||
}
|
}
|
||||||
if err := tun.setup(tun.config.IfName, addr, mtu); err != nil {
|
if err := tun.setup(tun.config.IfName, addr, mtu); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -188,4 +174,3 @@ func (tun *TunAdapter) _stop() error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user