diff --git a/src/tuntap/iface.go b/src/tuntap/iface.go index 836a9c61..50ea6dae 100644 --- a/src/tuntap/iface.go +++ b/src/tuntap/iface.go @@ -1,18 +1,107 @@ package tuntap import ( - //"github.com/yggdrasil-network/yggdrasil-go/src/address" + "crypto/ed25519" + + "github.com/yggdrasil-network/yggdrasil-go/src/address" "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 +func (tun *TunAdapter) doRead() { + var buf [TUN_OFFSET_BYTES + 65535]byte + for { + n, err := tun.iface.Read(buf[:], TUN_OFFSET_BYTES) + if n <= TUN_OFFSET_BYTES || err != nil { + tun.log.Errorln("Error reading TUN:", err) + ferr := tun.iface.Flush() + if ferr != nil { + tun.log.Errorln("Unable to flush packets:", ferr) + } + return + } + begin := TUN_OFFSET_BYTES + end := begin + n + bs := buf[begin:end] + if bs[0]&0xf0 != 0x60 { + continue // not IPv6 + } + 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 soruce address + } + if dstAddr.IsValid() { + tun.store.sendToAddress(dstAddr, bs) + } else if dstSubnet.IsValid() { + tun.store.sendToSubnet(dstSubnet, bs) + } + } +} + +func (tun *TunAdapter) doWrite() { + panic("TODO") + // Read from the packetconn + // Get the info from the store + // Check if addresses / subnets / etc are OK (both sides of connection) + var buf [TUN_OFFSET_BYTES + 65535]byte + for { + bs := buf[TUN_OFFSET_BYTES:] + n, from, err := tun.core.ReadFrom(bs) + if err != nil { + return + } + bs = bs[:n] + if bs[0]&0xf0 != 0x60 { + continue // not IPv6 + } + if len(bs) < 40 { + 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 != 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+n] + n, err = tun.iface.Write(bs, TUN_OFFSET_BYTES) + if err != nil { + tun.Act(nil, func() { + if !tun.isOpen { + tun.log.Errorln("TUN iface write error:", err) + } + }) + } + if n != len(bs) { + // TODO some kind of error reporting for a partial write + } + } +} + type tunWriter struct { phony.Inbox tun *TunAdapter diff --git a/src/tuntap/keystore.go b/src/tuntap/keystore.go index 8901965f..c7733a29 100644 --- a/src/tuntap/keystore.go +++ b/src/tuntap/keystore.go @@ -70,6 +70,7 @@ func (k *keyStore) sendToAddress(addr address.Address, bs []byte) { delete(k.addrBuffer, addr) } }) + panic("TODO") // TODO send lookup } } @@ -97,10 +98,11 @@ func (k *keyStore) sendToSubnet(subnet address.Subnet, bs []byte) { delete(k.subnetBuffer, subnet) } }) + panic("TODO") // TODO send lookup } } -func (k *keyStore) update(key ed25519.PublicKey) { +func (k *keyStore) update(key ed25519.PublicKey) *keyInfo { k.mutex.Lock() defer k.mutex.Unlock() var kArray keyArray @@ -130,6 +132,7 @@ func (k *keyStore) update(key ed25519.PublicKey) { } } k.resetTimeout(info) + return info } func (k *keyStore) resetTimeout(info *keyInfo) { diff --git a/src/tuntap/tun.go b/src/tuntap/tun.go index fc1b7eb9..7fa85175 100644 --- a/src/tuntap/tun.go +++ b/src/tuntap/tun.go @@ -171,6 +171,8 @@ func (tun *TunAdapter) _start() error { // TODO go tun.handler() tun.reader.Act(nil, tun.reader._read) // Start the reader tun.ckr.init(tun) + go tun.doRead() + go tun.doWrite() return nil }