mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-03-09 15:40:15 +00:00 
			
		
		
		
	Try to convert TUN/TAP to use new yggdrasil.Conn, search masks are still broken
This commit is contained in:
		
							parent
							
								
									319366513c
								
							
						
					
					
						commit
						d01662c1fb
					
				
					 14 changed files with 502 additions and 366 deletions
				
			
		|  | @ -10,7 +10,6 @@ import ( | ||||||
| 	"os/signal" | 	"os/signal" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"syscall" | 	"syscall" | ||||||
| 	"time" |  | ||||||
| 
 | 
 | ||||||
| 	"golang.org/x/text/encoding/unicode" | 	"golang.org/x/text/encoding/unicode" | ||||||
| 
 | 
 | ||||||
|  | @ -77,6 +76,7 @@ func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *nodeCo | ||||||
| 		panic(err) | 		panic(err) | ||||||
| 	} | 	} | ||||||
| 	json.Unmarshal(confJson, &cfg) | 	json.Unmarshal(confJson, &cfg) | ||||||
|  | 	/* | ||||||
| 		// For now we will do a little bit to help the user adjust their | 		// For now we will do a little bit to help the user adjust their | ||||||
| 		// configuration to match the new configuration format, as some of the key | 		// configuration to match the new configuration format, as some of the key | ||||||
| 		// names have changed recently. | 		// names have changed recently. | ||||||
|  | @ -148,6 +148,7 @@ func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *nodeCo | ||||||
| 				dat["Listen"] = []string{"tcp://" + listen} | 				dat["Listen"] = []string{"tcp://" + listen} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 	*/ | ||||||
| 	// Overlay our newly mapped configuration onto the autoconf node config that | 	// Overlay our newly mapped configuration onto the autoconf node config that | ||||||
| 	// we generated above. | 	// we generated above. | ||||||
| 	if err = mapstructure.Decode(dat, &cfg); err != nil { | 	if err = mapstructure.Decode(dat, &cfg); err != nil { | ||||||
|  | @ -249,8 +250,6 @@ func main() { | ||||||
| 	// Setup the Yggdrasil node itself. The node{} type includes a Core, so we | 	// Setup the Yggdrasil node itself. The node{} type includes a Core, so we | ||||||
| 	// don't need to create this manually. | 	// don't need to create this manually. | ||||||
| 	n := node{} | 	n := node{} | ||||||
| 	// Before we start the node, set the TUN/TAP to be our router adapter |  | ||||||
| 	n.core.SetRouterAdapter(&n.tuntap) |  | ||||||
| 	// Now start Yggdrasil - this starts the DHT, router, switch and other core | 	// Now start Yggdrasil - this starts the DHT, router, switch and other core | ||||||
| 	// components needed for Yggdrasil to operate | 	// components needed for Yggdrasil to operate | ||||||
| 	state, err := n.core.Start(cfg, logger) | 	state, err := n.core.Start(cfg, logger) | ||||||
|  | @ -263,12 +262,27 @@ func main() { | ||||||
| 	if err := n.multicast.Start(); err != nil { | 	if err := n.multicast.Start(); err != nil { | ||||||
| 		logger.Errorln("An error occurred starting multicast:", err) | 		logger.Errorln("An error occurred starting multicast:", err) | ||||||
| 	} | 	} | ||||||
|  | 	// Start the TUN/TAP interface | ||||||
|  | 	if listener, err := n.core.ConnListen(); err == nil { | ||||||
|  | 		if dialer, err := n.core.ConnDialer(); err == nil { | ||||||
|  | 			logger.Println("Got listener", listener, "and dialer", dialer) | ||||||
|  | 			n.tuntap.Init(state, logger, listener, dialer) | ||||||
|  | 			if err := n.tuntap.Start(); err != nil { | ||||||
|  | 				logger.Errorln("An error occurred starting TUN/TAP:", err) | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			logger.Errorln("Unable to get Dialer:", err) | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		logger.Errorln("Unable to get Listener:", err) | ||||||
|  | 	} | ||||||
| 	// The Stop function ensures that the TUN/TAP adapter is correctly shut down | 	// The Stop function ensures that the TUN/TAP adapter is correctly shut down | ||||||
| 	// before the program exits. | 	// before the program exits. | ||||||
| 	defer func() { | 	defer func() { | ||||||
| 		n.core.Stop() | 		n.core.Stop() | ||||||
| 	}() | 	}() | ||||||
| 	// Listen for new sessions | 	// Listen for new sessions | ||||||
|  | 	/* | ||||||
| 		go func() { | 		go func() { | ||||||
| 			listener, err := n.core.ListenConn() | 			listener, err := n.core.ListenConn() | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
|  | @ -329,6 +343,7 @@ func main() { | ||||||
| 				} | 				} | ||||||
| 			}() | 			}() | ||||||
| 		}() | 		}() | ||||||
|  | 	*/ | ||||||
| 	// Make some nice output that tells us what our IPv6 address and subnet are. | 	// Make some nice output that tells us what our IPv6 address and subnet are. | ||||||
| 	// This is just logged to stdout for the user. | 	// This is just logged to stdout for the user. | ||||||
| 	address := n.core.Address() | 	address := n.core.Address() | ||||||
|  |  | ||||||
|  | @ -37,10 +37,37 @@ func (n *NodeID) String() string { | ||||||
| 	return hex.EncodeToString(n[:]) | 	return hex.EncodeToString(n[:]) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Network returns "nodeid" nearly always right now. | ||||||
| func (n *NodeID) Network() string { | func (n *NodeID) Network() string { | ||||||
| 	return "nodeid" | 	return "nodeid" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // PrefixLength returns the number of bits set in a masked NodeID. | ||||||
|  | func (n *NodeID) PrefixLength() int { | ||||||
|  | 	var len int | ||||||
|  | 	for i, v := range *n { | ||||||
|  | 		_, _ = i, v | ||||||
|  | 		if v == 0xff { | ||||||
|  | 			len += 8 | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		for v&0x80 != 0 { | ||||||
|  | 			len++ | ||||||
|  | 			v <<= 1 | ||||||
|  | 		} | ||||||
|  | 		if v != 0 { | ||||||
|  | 			return -1 | ||||||
|  | 		} | ||||||
|  | 		for i++; i < NodeIDLen; i++ { | ||||||
|  | 			if n[i] != 0 { | ||||||
|  | 				return -1 | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		break | ||||||
|  | 	} | ||||||
|  | 	return len | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func GetNodeID(pub *BoxPubKey) *NodeID { | func GetNodeID(pub *BoxPubKey) *NodeID { | ||||||
| 	h := sha512.Sum512(pub[:]) | 	h := sha512.Sum512(pub[:]) | ||||||
| 	return (*NodeID)(&h) | 	return (*NodeID)(&h) | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ package tuntap | ||||||
| // This manages the tun driver to send/recv packets to/from applications | // This manages the tun driver to send/recv packets to/from applications | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"encoding/hex" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net" | 	"net" | ||||||
|  | @ -11,16 +11,12 @@ import ( | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/gologme/log" | 	"github.com/gologme/log" | ||||||
| 	"golang.org/x/net/icmp" |  | ||||||
| 	"golang.org/x/net/ipv6" |  | ||||||
| 
 |  | ||||||
| 	"github.com/songgao/packets/ethernet" |  | ||||||
| 	"github.com/yggdrasil-network/water" | 	"github.com/yggdrasil-network/water" | ||||||
| 
 | 
 | ||||||
| 	"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/defaults" | 	"github.com/yggdrasil-network/yggdrasil-go/src/defaults" | ||||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/util" |  | ||||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil" | 	"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -32,7 +28,13 @@ const tun_ETHER_HEADER_LENGTH = 14 | ||||||
| // you should pass this object to the yggdrasil.SetRouterAdapter() function | // you should pass this object to the yggdrasil.SetRouterAdapter() function | ||||||
| // before calling yggdrasil.Start(). | // before calling yggdrasil.Start(). | ||||||
| type TunAdapter struct { | type TunAdapter struct { | ||||||
| 	yggdrasil.Adapter | 	config      *config.NodeState | ||||||
|  | 	log         *log.Logger | ||||||
|  | 	reconfigure chan chan error | ||||||
|  | 	conns       map[crypto.NodeID]yggdrasil.Conn | ||||||
|  | 	connsMutex  sync.RWMutex | ||||||
|  | 	listener    *yggdrasil.Listener | ||||||
|  | 	dialer      *yggdrasil.Dialer | ||||||
| 	addr        address.Address | 	addr        address.Address | ||||||
| 	subnet      address.Subnet | 	subnet      address.Subnet | ||||||
| 	icmpv6      ICMPv6 | 	icmpv6      ICMPv6 | ||||||
|  | @ -94,62 +96,48 @@ func MaximumMTU() int { | ||||||
| 	return defaults.GetDefaults().MaximumIfMTU | 	return defaults.GetDefaults().MaximumIfMTU | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Init initialises the TUN/TAP adapter. | // Init initialises the TUN/TAP module. You must have acquired a Listener from | ||||||
| func (tun *TunAdapter) Init(config *config.NodeState, log *log.Logger, send chan<- []byte, recv <-chan []byte, reject <-chan yggdrasil.RejectedPacket) { | // the Yggdrasil core before this point and it must not be in use elsewhere. | ||||||
| 	tun.Adapter.Init(config, log, send, recv, reject) | func (tun *TunAdapter) Init(config *config.NodeState, log *log.Logger, listener *yggdrasil.Listener, dialer *yggdrasil.Dialer) { | ||||||
| 	tun.icmpv6.Init(tun) | 	tun.config = config | ||||||
| 	go func() { | 	tun.log = log | ||||||
| 		for { | 	tun.listener = listener | ||||||
| 			e := <-tun.Reconfigure | 	tun.dialer = dialer | ||||||
| 			tun.Config.Mutex.RLock() | 	tun.conns = make(map[crypto.NodeID]yggdrasil.Conn) | ||||||
| 			updated := tun.Config.Current.IfName != tun.Config.Previous.IfName || |  | ||||||
| 				tun.Config.Current.IfTAPMode != tun.Config.Previous.IfTAPMode || |  | ||||||
| 				tun.Config.Current.IfMTU != tun.Config.Previous.IfMTU |  | ||||||
| 			tun.Config.Mutex.RUnlock() |  | ||||||
| 			if updated { |  | ||||||
| 				tun.Log.Warnln("Reconfiguring TUN/TAP is not supported yet") |  | ||||||
| 				e <- nil |  | ||||||
| 			} else { |  | ||||||
| 				e <- nil |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	}() |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Start the setup process for the TUN/TAP adapter. If successful, starts the | // Start the setup process for the TUN/TAP adapter. If successful, starts the | ||||||
| // read/write goroutines to handle packets on that interface. | // read/write goroutines to handle packets on that interface. | ||||||
| func (tun *TunAdapter) Start(a address.Address, s address.Subnet) error { | func (tun *TunAdapter) Start() error { | ||||||
| 	tun.addr = a | 	tun.config.Mutex.Lock() | ||||||
| 	tun.subnet = s | 	defer tun.config.Mutex.Unlock() | ||||||
| 	if tun.Config == nil { | 	if tun.config == nil || tun.listener == nil || tun.dialer == nil { | ||||||
| 		return errors.New("No configuration available to TUN/TAP") | 		return errors.New("No configuration available to TUN/TAP") | ||||||
| 	} | 	} | ||||||
| 	tun.Config.Mutex.RLock() | 	var boxPub crypto.BoxPubKey | ||||||
| 	ifname := tun.Config.Current.IfName | 	boxPubHex, err := hex.DecodeString(tun.config.Current.EncryptionPublicKey) | ||||||
| 	iftapmode := tun.Config.Current.IfTAPMode | 	if err != nil { | ||||||
| 	addr := fmt.Sprintf("%s/%d", net.IP(tun.addr[:]).String(), 8*len(address.GetPrefix())-1) | 		return err | ||||||
| 	mtu := tun.Config.Current.IfMTU | 	} | ||||||
| 	tun.Config.Mutex.RUnlock() | 	copy(boxPub[:], boxPubHex) | ||||||
|  | 	nodeID := crypto.GetNodeID(&boxPub) | ||||||
|  | 	tun.addr = *address.AddrForNodeID(nodeID) | ||||||
|  | 	tun.subnet = *address.SubnetForNodeID(nodeID) | ||||||
|  | 	tun.mtu = tun.config.Current.IfMTU | ||||||
|  | 	ifname := tun.config.Current.IfName | ||||||
|  | 	iftapmode := tun.config.Current.IfTAPMode | ||||||
| 	if ifname != "none" { | 	if ifname != "none" { | ||||||
| 		if err := tun.setup(ifname, iftapmode, addr, mtu); err != nil { | 		if err := tun.setup(ifname, iftapmode, net.IP(tun.addr[:]).String(), tun.mtu); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if ifname == "none" || ifname == "dummy" { | 	if ifname == "none" || ifname == "dummy" { | ||||||
| 		tun.Log.Debugln("Not starting TUN/TAP as ifname is none or dummy") | 		tun.log.Debugln("Not starting TUN/TAP as ifname is none or dummy") | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	tun.mutex.Lock() | 	tun.mutex.Lock() | ||||||
| 	tun.isOpen = true | 	tun.isOpen = true | ||||||
| 	tun.mutex.Unlock() | 	tun.mutex.Unlock() | ||||||
| 	go func() { |  | ||||||
| 		tun.Log.Debugln("Starting TUN/TAP reader goroutine") |  | ||||||
| 		tun.Log.Errorln("WARNING: tun.read() exited with error:", tun.read()) |  | ||||||
| 	}() |  | ||||||
| 	go func() { |  | ||||||
| 		tun.Log.Debugln("Starting TUN/TAP writer goroutine") |  | ||||||
| 		tun.Log.Errorln("WARNING: tun.write() exited with error:", tun.write()) |  | ||||||
| 	}() |  | ||||||
| 	if iftapmode { | 	if iftapmode { | ||||||
| 		go func() { | 		go func() { | ||||||
| 			for { | 			for { | ||||||
|  | @ -167,12 +155,153 @@ func (tun *TunAdapter) Start(a address.Address, s address.Subnet) error { | ||||||
| 			} | 			} | ||||||
| 		}() | 		}() | ||||||
| 	} | 	} | ||||||
|  | 	tun.icmpv6.Init(tun) | ||||||
|  | 	go func() { | ||||||
|  | 		for { | ||||||
|  | 			e := <-tun.reconfigure | ||||||
|  | 			e <- nil | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 	go tun.handler() | ||||||
|  | 	go tun.ifaceReader() | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (tun *TunAdapter) handler() error { | ||||||
|  | 	for { | ||||||
|  | 		// Accept the incoming connection | ||||||
|  | 		conn, err := tun.listener.Accept() | ||||||
|  | 		if err != nil { | ||||||
|  | 			tun.log.Errorln("TUN/TAP error accepting connection:", err) | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		tun.log.Println("Accepted connection from", conn.RemoteAddr()) | ||||||
|  | 		go tun.connReader(conn) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (tun *TunAdapter) connReader(conn *yggdrasil.Conn) error { | ||||||
|  | 	b := make([]byte, 65535) | ||||||
|  | 	for { | ||||||
|  | 		n, err := conn.Read(b) | ||||||
|  | 		if err != nil { | ||||||
|  | 			tun.log.Errorln("TUN/TAP read error:", err) | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		if n == 0 { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		w, err := tun.iface.Write(b[:n]) | ||||||
|  | 		if err != nil { | ||||||
|  | 			tun.log.Errorln("TUN/TAP failed to write to interface:", err) | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		if w != n { | ||||||
|  | 			tun.log.Errorln("TUN/TAP wrote", w, "instead of", n, "which is bad") | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (tun *TunAdapter) ifaceReader() error { | ||||||
|  | 	tun.log.Println("Start TUN reader") | ||||||
|  | 	bs := make([]byte, 65535) | ||||||
|  | 	for { | ||||||
|  | 		n, err := tun.iface.Read(bs) | ||||||
|  | 		if err != nil { | ||||||
|  | 			tun.log.Errorln("TUN/TAP iface read error:", err) | ||||||
|  | 		} | ||||||
|  | 		// Look up if the dstination address is somewhere we already have an | ||||||
|  | 		// open connection to | ||||||
|  | 		var srcAddr address.Address | ||||||
|  | 		var dstAddr address.Address | ||||||
|  | 		var dstNodeID *crypto.NodeID | ||||||
|  | 		var dstNodeIDMask *crypto.NodeID | ||||||
|  | 		var dstSnet address.Subnet | ||||||
|  | 		var addrlen int | ||||||
|  | 		if bs[0]&0xf0 == 0x60 { | ||||||
|  | 			// Check if we have a fully-sized header | ||||||
|  | 			if len(bs) < 40 { | ||||||
|  | 				panic("Tried to send a packet shorter than an IPv6 header...") | ||||||
|  | 			} | ||||||
|  | 			// IPv6 address | ||||||
|  | 			addrlen = 16 | ||||||
|  | 			copy(srcAddr[:addrlen], bs[8:]) | ||||||
|  | 			copy(dstAddr[:addrlen], bs[24:]) | ||||||
|  | 			copy(dstSnet[:addrlen/2], bs[24:]) | ||||||
|  | 		} else if bs[0]&0xf0 == 0x40 { | ||||||
|  | 			// Check if we have a fully-sized header | ||||||
|  | 			if len(bs) < 20 { | ||||||
|  | 				panic("Tried to send a packet shorter than an IPv4 header...") | ||||||
|  | 			} | ||||||
|  | 			// IPv4 address | ||||||
|  | 			addrlen = 4 | ||||||
|  | 			copy(srcAddr[:addrlen], bs[12:]) | ||||||
|  | 			copy(dstAddr[:addrlen], bs[16:]) | ||||||
|  | 		} else { | ||||||
|  | 			// Unknown address length | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		dstNodeID, dstNodeIDMask = dstAddr.GetNodeIDandMask() | ||||||
|  | 		// Do we have an active connection for this node ID? | ||||||
|  | 		if conn, isIn := tun.conns[*dstNodeID]; isIn { | ||||||
|  | 			fmt.Println("We have a connection for", *dstNodeID) | ||||||
|  | 			w, err := conn.Write(bs) | ||||||
|  | 			if err != nil { | ||||||
|  | 				fmt.Println("Unable to write to remote:", err) | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			if w != n { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			fmt.Println("Opening connection for", *dstNodeID) | ||||||
|  | 			tun.connsMutex.Lock() | ||||||
|  | 			maskstr := hex.EncodeToString(dstNodeID[:]) | ||||||
|  | 			masklen := dstNodeIDMask.PrefixLength() | ||||||
|  | 			cidr := fmt.Sprintf("%s/%d", maskstr, masklen) | ||||||
|  | 			if conn, err := tun.dialer.Dial("nodeid", cidr); err == nil { | ||||||
|  | 				tun.conns[*dstNodeID] = conn | ||||||
|  | 				go tun.connReader(&conn) | ||||||
|  | 			} else { | ||||||
|  | 				fmt.Println("Error dialing:", err) | ||||||
|  | 			} | ||||||
|  | 			tun.connsMutex.Unlock() | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/*if !r.cryptokey.isValidSource(srcAddr, addrlen) { | ||||||
|  | 			// The packet had a src address that doesn't belong to us or our | ||||||
|  | 			// configured crypto-key routing src subnets | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		if !dstAddr.IsValid() && !dstSnet.IsValid() { | ||||||
|  | 			// The addresses didn't match valid Yggdrasil node addresses so let's see | ||||||
|  | 			// whether it matches a crypto-key routing range instead | ||||||
|  | 			if key, err := r.cryptokey.getPublicKeyForAddress(dstAddr, addrlen); err == nil { | ||||||
|  | 				// A public key was found, get the node ID for the search | ||||||
|  | 				dstPubKey = &key | ||||||
|  | 				dstNodeID = crypto.GetNodeID(dstPubKey) | ||||||
|  | 				// Do a quick check to ensure that the node ID refers to a vaild Yggdrasil | ||||||
|  | 				// address or subnet - this might be superfluous | ||||||
|  | 				addr := *address.AddrForNodeID(dstNodeID) | ||||||
|  | 				copy(dstAddr[:], addr[:]) | ||||||
|  | 				copy(dstSnet[:], addr[:]) | ||||||
|  | 				if !dstAddr.IsValid() && !dstSnet.IsValid() { | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				// No public key was found in the CKR table so we've exhausted our options | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		}*/ | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Writes a packet to the TUN/TAP adapter. If the adapter is running in TAP | // Writes a packet to the TUN/TAP adapter. If the adapter is running in TAP | ||||||
| // mode then additional ethernet encapsulation is added for the benefit of the | // mode then additional ethernet encapsulation is added for the benefit of the | ||||||
| // host operating system. | // host operating system. | ||||||
|  | /* | ||||||
| func (tun *TunAdapter) write() error { | func (tun *TunAdapter) write() error { | ||||||
| 	for { | 	for { | ||||||
| 		select { | 		select { | ||||||
|  | @ -205,36 +334,36 @@ func (tun *TunAdapter) write() error { | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
| 			if tun.iface.IsTAP() { | 			if tun.iface.IsTAP() { | ||||||
| 				var destAddr address.Address | 				var dstAddr address.Address | ||||||
| 				if data[0]&0xf0 == 0x60 { | 				if data[0]&0xf0 == 0x60 { | ||||||
| 					if len(data) < 40 { | 					if len(data) < 40 { | ||||||
| 						//panic("Tried to send a packet shorter than an IPv6 header...") | 						//panic("Tried to send a packet shorter than an IPv6 header...") | ||||||
| 						util.PutBytes(data) | 						util.PutBytes(data) | ||||||
| 						continue | 						continue | ||||||
| 					} | 					} | ||||||
| 					copy(destAddr[:16], data[24:]) | 					copy(dstAddr[:16], data[24:]) | ||||||
| 				} else if data[0]&0xf0 == 0x40 { | 				} else if data[0]&0xf0 == 0x40 { | ||||||
| 					if len(data) < 20 { | 					if len(data) < 20 { | ||||||
| 						//panic("Tried to send a packet shorter than an IPv4 header...") | 						//panic("Tried to send a packet shorter than an IPv4 header...") | ||||||
| 						util.PutBytes(data) | 						util.PutBytes(data) | ||||||
| 						continue | 						continue | ||||||
| 					} | 					} | ||||||
| 					copy(destAddr[:4], data[16:]) | 					copy(dstAddr[:4], data[16:]) | ||||||
| 				} else { | 				} else { | ||||||
| 					return errors.New("Invalid address family") | 					return errors.New("Invalid address family") | ||||||
| 				} | 				} | ||||||
| 				sendndp := func(destAddr address.Address) { | 				sendndp := func(dstAddr address.Address) { | ||||||
| 					neigh, known := tun.icmpv6.peermacs[destAddr] | 					neigh, known := tun.icmpv6.peermacs[dstAddr] | ||||||
| 					known = known && (time.Since(neigh.lastsolicitation).Seconds() < 30) | 					known = known && (time.Since(neigh.lastsolicitation).Seconds() < 30) | ||||||
| 					if !known { | 					if !known { | ||||||
| 						request, err := tun.icmpv6.CreateNDPL2(destAddr) | 						request, err := tun.icmpv6.CreateNDPL2(dstAddr) | ||||||
| 						if err != nil { | 						if err != nil { | ||||||
| 							panic(err) | 							panic(err) | ||||||
| 						} | 						} | ||||||
| 						if _, err := tun.iface.Write(request); err != nil { | 						if _, err := tun.iface.Write(request); err != nil { | ||||||
| 							panic(err) | 							panic(err) | ||||||
| 						} | 						} | ||||||
| 						tun.icmpv6.peermacs[destAddr] = neighbor{ | 						tun.icmpv6.peermacs[dstAddr] = neighbor{ | ||||||
| 							lastsolicitation: time.Now(), | 							lastsolicitation: time.Now(), | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
|  | @ -242,19 +371,19 @@ func (tun *TunAdapter) write() error { | ||||||
| 				var peermac macAddress | 				var peermac macAddress | ||||||
| 				var peerknown bool | 				var peerknown bool | ||||||
| 				if data[0]&0xf0 == 0x40 { | 				if data[0]&0xf0 == 0x40 { | ||||||
| 					destAddr = tun.addr | 					dstAddr = tun.addr | ||||||
| 				} else if data[0]&0xf0 == 0x60 { | 				} else if data[0]&0xf0 == 0x60 { | ||||||
| 					if !bytes.Equal(tun.addr[:16], destAddr[:16]) && !bytes.Equal(tun.subnet[:8], destAddr[:8]) { | 					if !bytes.Equal(tun.addr[:16], dstAddr[:16]) && !bytes.Equal(tun.subnet[:8], dstAddr[:8]) { | ||||||
| 						destAddr = tun.addr | 						dstAddr = tun.addr | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				if neighbor, ok := tun.icmpv6.peermacs[destAddr]; ok && neighbor.learned { | 				if neighbor, ok := tun.icmpv6.peermacs[dstAddr]; ok && neighbor.learned { | ||||||
| 					peermac = neighbor.mac | 					peermac = neighbor.mac | ||||||
| 					peerknown = true | 					peerknown = true | ||||||
| 				} else if neighbor, ok := tun.icmpv6.peermacs[tun.addr]; ok && neighbor.learned { | 				} else if neighbor, ok := tun.icmpv6.peermacs[tun.addr]; ok && neighbor.learned { | ||||||
| 					peermac = neighbor.mac | 					peermac = neighbor.mac | ||||||
| 					peerknown = true | 					peerknown = true | ||||||
| 					sendndp(destAddr) | 					sendndp(dstAddr) | ||||||
| 				} else { | 				} else { | ||||||
| 					sendndp(tun.addr) | 					sendndp(tun.addr) | ||||||
| 				} | 				} | ||||||
|  | @ -359,3 +488,4 @@ func (tun *TunAdapter) Close() error { | ||||||
| 	} | 	} | ||||||
| 	return tun.iface.Close() | 	return tun.iface.Close() | ||||||
| } | } | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | @ -109,14 +109,14 @@ func (tun *TunAdapter) setupAddress(addr string) error { | ||||||
| 
 | 
 | ||||||
| 	// Create system socket | 	// Create system socket | ||||||
| 	if sfd, err = unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0); err != nil { | 	if sfd, err = unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0); err != nil { | ||||||
| 		tun.Log.Printf("Create AF_INET socket failed: %v.", err) | 		tun.log.Printf("Create AF_INET socket failed: %v.", err) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Friendly output | 	// Friendly output | ||||||
| 	tun.Log.Infof("Interface name: %s", tun.iface.Name()) | 	tun.log.Infof("Interface name: %s", tun.iface.Name()) | ||||||
| 	tun.Log.Infof("Interface IPv6: %s", addr) | 	tun.log.Infof("Interface IPv6: %s", addr) | ||||||
| 	tun.Log.Infof("Interface MTU: %d", tun.mtu) | 	tun.log.Infof("Interface MTU: %d", tun.mtu) | ||||||
| 
 | 
 | ||||||
| 	// Create the MTU request | 	// Create the MTU request | ||||||
| 	var ir in6_ifreq_mtu | 	var ir in6_ifreq_mtu | ||||||
|  | @ -126,15 +126,15 @@ func (tun *TunAdapter) setupAddress(addr string) error { | ||||||
| 	// Set the MTU | 	// Set the MTU | ||||||
| 	if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(sfd), uintptr(syscall.SIOCSIFMTU), uintptr(unsafe.Pointer(&ir))); errno != 0 { | 	if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(sfd), uintptr(syscall.SIOCSIFMTU), uintptr(unsafe.Pointer(&ir))); errno != 0 { | ||||||
| 		err = errno | 		err = errno | ||||||
| 		tun.Log.Errorf("Error in SIOCSIFMTU: %v", errno) | 		tun.log.Errorf("Error in SIOCSIFMTU: %v", errno) | ||||||
| 
 | 
 | ||||||
| 		// Fall back to ifconfig to set the MTU | 		// Fall back to ifconfig to set the MTU | ||||||
| 		cmd := exec.Command("ifconfig", tun.iface.Name(), "mtu", string(tun.mtu)) | 		cmd := exec.Command("ifconfig", tun.iface.Name(), "mtu", string(tun.mtu)) | ||||||
| 		tun.Log.Warnf("Using ifconfig as fallback: %v", strings.Join(cmd.Args, " ")) | 		tun.log.Warnf("Using ifconfig as fallback: %v", strings.Join(cmd.Args, " ")) | ||||||
| 		output, err := cmd.CombinedOutput() | 		output, err := cmd.CombinedOutput() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			tun.Log.Errorf("SIOCSIFMTU fallback failed: %v.", err) | 			tun.log.Errorf("SIOCSIFMTU fallback failed: %v.", err) | ||||||
| 			tun.Log.Traceln(string(output)) | 			tun.log.Traceln(string(output)) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -155,15 +155,15 @@ func (tun *TunAdapter) setupAddress(addr string) error { | ||||||
| 	// Set the interface address | 	// Set the interface address | ||||||
| 	if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(sfd), uintptr(SIOCSIFADDR_IN6), uintptr(unsafe.Pointer(&ar))); errno != 0 { | 	if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(sfd), uintptr(SIOCSIFADDR_IN6), uintptr(unsafe.Pointer(&ar))); errno != 0 { | ||||||
| 		err = errno | 		err = errno | ||||||
| 		tun.Log.Errorf("Error in SIOCSIFADDR_IN6: %v", errno) | 		tun.log.Errorf("Error in SIOCSIFADDR_IN6: %v", errno) | ||||||
| 
 | 
 | ||||||
| 		// Fall back to ifconfig to set the address | 		// Fall back to ifconfig to set the address | ||||||
| 		cmd := exec.Command("ifconfig", tun.iface.Name(), "inet6", addr) | 		cmd := exec.Command("ifconfig", tun.iface.Name(), "inet6", addr) | ||||||
| 		tun.Log.Warnf("Using ifconfig as fallback: %v", strings.Join(cmd.Args, " ")) | 		tun.log.Warnf("Using ifconfig as fallback: %v", strings.Join(cmd.Args, " ")) | ||||||
| 		output, err := cmd.CombinedOutput() | 		output, err := cmd.CombinedOutput() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			tun.Log.Errorf("SIOCSIFADDR_IN6 fallback failed: %v.", err) | 			tun.log.Errorf("SIOCSIFADDR_IN6 fallback failed: %v.", err) | ||||||
| 			tun.Log.Traceln(string(output)) | 			tun.log.Traceln(string(output)) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ import ( | ||||||
| // Configures the "utun" adapter with the correct IPv6 address and MTU. | // Configures the "utun" adapter with the correct IPv6 address and MTU. | ||||||
| func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int) error { | func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int) error { | ||||||
| 	if iftapmode { | 	if iftapmode { | ||||||
| 		tun.Log.Warnln("TAP mode is not supported on this platform, defaulting to TUN") | 		tun.log.Warnln("TAP mode is not supported on this platform, defaulting to TUN") | ||||||
| 	} | 	} | ||||||
| 	config := water.Config{DeviceType: water.TUN} | 	config := water.Config{DeviceType: water.TUN} | ||||||
| 	iface, err := water.New(config) | 	iface, err := water.New(config) | ||||||
|  | @ -69,7 +69,7 @@ func (tun *TunAdapter) setupAddress(addr string) error { | ||||||
| 	var err error | 	var err error | ||||||
| 
 | 
 | ||||||
| 	if fd, err = unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, 0); err != nil { | 	if fd, err = unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, 0); err != nil { | ||||||
| 		tun.Log.Printf("Create AF_SYSTEM socket failed: %v.", err) | 		tun.log.Printf("Create AF_SYSTEM socket failed: %v.", err) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -98,19 +98,19 @@ func (tun *TunAdapter) setupAddress(addr string) error { | ||||||
| 	copy(ir.ifr_name[:], tun.iface.Name()) | 	copy(ir.ifr_name[:], tun.iface.Name()) | ||||||
| 	ir.ifru_mtu = uint32(tun.mtu) | 	ir.ifru_mtu = uint32(tun.mtu) | ||||||
| 
 | 
 | ||||||
| 	tun.Log.Infof("Interface name: %s", ar.ifra_name) | 	tun.log.Infof("Interface name: %s", ar.ifra_name) | ||||||
| 	tun.Log.Infof("Interface IPv6: %s", addr) | 	tun.log.Infof("Interface IPv6: %s", addr) | ||||||
| 	tun.Log.Infof("Interface MTU: %d", ir.ifru_mtu) | 	tun.log.Infof("Interface MTU: %d", ir.ifru_mtu) | ||||||
| 
 | 
 | ||||||
| 	if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(darwin_SIOCAIFADDR_IN6), uintptr(unsafe.Pointer(&ar))); errno != 0 { | 	if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(darwin_SIOCAIFADDR_IN6), uintptr(unsafe.Pointer(&ar))); errno != 0 { | ||||||
| 		err = errno | 		err = errno | ||||||
| 		tun.Log.Errorf("Error in darwin_SIOCAIFADDR_IN6: %v", errno) | 		tun.log.Errorf("Error in darwin_SIOCAIFADDR_IN6: %v", errno) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(unix.SIOCSIFMTU), uintptr(unsafe.Pointer(&ir))); errno != 0 { | 	if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(unix.SIOCSIFMTU), uintptr(unsafe.Pointer(&ir))); errno != 0 { | ||||||
| 		err = errno | 		err = errno | ||||||
| 		tun.Log.Errorf("Error in SIOCSIFMTU: %v", errno) | 		tun.log.Errorf("Error in SIOCSIFMTU: %v", errno) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -40,9 +40,9 @@ func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	// Friendly output | 	// Friendly output | ||||||
| 	tun.Log.Infof("Interface name: %s", tun.iface.Name()) | 	tun.log.Infof("Interface name: %s", tun.iface.Name()) | ||||||
| 	tun.Log.Infof("Interface IPv6: %s", addr) | 	tun.log.Infof("Interface IPv6: %s", addr) | ||||||
| 	tun.Log.Infof("Interface MTU: %d", tun.mtu) | 	tun.log.Infof("Interface MTU: %d", tun.mtu) | ||||||
| 	return tun.setupAddress(addr) | 	return tun.setupAddress(addr) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,6 +28,6 @@ func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int | ||||||
| // We don't know how to set the IPv6 address on an unknown platform, therefore | // We don't know how to set the IPv6 address on an unknown platform, therefore | ||||||
| // write about it to stdout and don't try to do anything further. | // write about it to stdout and don't try to do anything further. | ||||||
| func (tun *TunAdapter) setupAddress(addr string) error { | func (tun *TunAdapter) setupAddress(addr string) error { | ||||||
| 	tun.Log.Warnln("Platform not supported, you must set the address of", tun.iface.Name(), "to", addr) | 	tun.log.Warnln("Platform not supported, you must set the address of", tun.iface.Name(), "to", addr) | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -15,7 +15,7 @@ import ( | ||||||
| // delegate the hard work to "netsh". | // delegate the hard work to "netsh". | ||||||
| func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int) error { | func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int) error { | ||||||
| 	if !iftapmode { | 	if !iftapmode { | ||||||
| 		tun.Log.Warnln("TUN mode is not supported on this platform, defaulting to TAP") | 		tun.log.Warnln("TUN mode is not supported on this platform, defaulting to TAP") | ||||||
| 	} | 	} | ||||||
| 	config := water.Config{DeviceType: water.TAP} | 	config := water.Config{DeviceType: water.TAP} | ||||||
| 	config.PlatformSpecificParams.ComponentID = "tap0901" | 	config.PlatformSpecificParams.ComponentID = "tap0901" | ||||||
|  | @ -31,19 +31,19 @@ func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int | ||||||
| 	} | 	} | ||||||
| 	// Disable/enable the interface to resets its configuration (invalidating iface) | 	// Disable/enable the interface to resets its configuration (invalidating iface) | ||||||
| 	cmd := exec.Command("netsh", "interface", "set", "interface", iface.Name(), "admin=DISABLED") | 	cmd := exec.Command("netsh", "interface", "set", "interface", iface.Name(), "admin=DISABLED") | ||||||
| 	tun.Log.Printf("netsh command: %v", strings.Join(cmd.Args, " ")) | 	tun.log.Printf("netsh command: %v", strings.Join(cmd.Args, " ")) | ||||||
| 	output, err := cmd.CombinedOutput() | 	output, err := cmd.CombinedOutput() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		tun.Log.Errorf("Windows netsh failed: %v.", err) | 		tun.log.Errorf("Windows netsh failed: %v.", err) | ||||||
| 		tun.Log.Traceln(string(output)) | 		tun.log.Traceln(string(output)) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	cmd = exec.Command("netsh", "interface", "set", "interface", iface.Name(), "admin=ENABLED") | 	cmd = exec.Command("netsh", "interface", "set", "interface", iface.Name(), "admin=ENABLED") | ||||||
| 	tun.Log.Printf("netsh command: %v", strings.Join(cmd.Args, " ")) | 	tun.log.Printf("netsh command: %v", strings.Join(cmd.Args, " ")) | ||||||
| 	output, err = cmd.CombinedOutput() | 	output, err = cmd.CombinedOutput() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		tun.Log.Errorf("Windows netsh failed: %v.", err) | 		tun.log.Errorf("Windows netsh failed: %v.", err) | ||||||
| 		tun.Log.Traceln(string(output)) | 		tun.log.Traceln(string(output)) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	// Get a new iface | 	// Get a new iface | ||||||
|  | @ -58,9 +58,9 @@ func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int | ||||||
| 		panic(err) | 		panic(err) | ||||||
| 	} | 	} | ||||||
| 	// Friendly output | 	// Friendly output | ||||||
| 	tun.Log.Infof("Interface name: %s", tun.iface.Name()) | 	tun.log.Infof("Interface name: %s", tun.iface.Name()) | ||||||
| 	tun.Log.Infof("Interface IPv6: %s", addr) | 	tun.log.Infof("Interface IPv6: %s", addr) | ||||||
| 	tun.Log.Infof("Interface MTU: %d", tun.mtu) | 	tun.log.Infof("Interface MTU: %d", tun.mtu) | ||||||
| 	return tun.setupAddress(addr) | 	return tun.setupAddress(addr) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -71,11 +71,11 @@ func (tun *TunAdapter) setupMTU(mtu int) error { | ||||||
| 		fmt.Sprintf("interface=%s", tun.iface.Name()), | 		fmt.Sprintf("interface=%s", tun.iface.Name()), | ||||||
| 		fmt.Sprintf("mtu=%d", mtu), | 		fmt.Sprintf("mtu=%d", mtu), | ||||||
| 		"store=active") | 		"store=active") | ||||||
| 	tun.Log.Debugln("netsh command: %v", strings.Join(cmd.Args, " ")) | 	tun.log.Debugln("netsh command: %v", strings.Join(cmd.Args, " ")) | ||||||
| 	output, err := cmd.CombinedOutput() | 	output, err := cmd.CombinedOutput() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		tun.Log.Errorf("Windows netsh failed: %v.", err) | 		tun.log.Errorf("Windows netsh failed: %v.", err) | ||||||
| 		tun.Log.Traceln(string(output)) | 		tun.log.Traceln(string(output)) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
|  | @ -88,11 +88,11 @@ func (tun *TunAdapter) setupAddress(addr string) error { | ||||||
| 		fmt.Sprintf("interface=%s", tun.iface.Name()), | 		fmt.Sprintf("interface=%s", tun.iface.Name()), | ||||||
| 		fmt.Sprintf("addr=%s", addr), | 		fmt.Sprintf("addr=%s", addr), | ||||||
| 		"store=active") | 		"store=active") | ||||||
| 	tun.Log.Debugln("netsh command: %v", strings.Join(cmd.Args, " ")) | 	tun.log.Debugln("netsh command: %v", strings.Join(cmd.Args, " ")) | ||||||
| 	output, err := cmd.CombinedOutput() | 	output, err := cmd.CombinedOutput() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		tun.Log.Errorf("Windows netsh failed: %v.", err) | 		tun.log.Errorf("Windows netsh failed: %v.", err) | ||||||
| 		tun.Log.Traceln(string(output)) | 		tun.log.Traceln(string(output)) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
|  |  | ||||||
|  | @ -1,47 +0,0 @@ | ||||||
| package yggdrasil |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"github.com/gologme/log" |  | ||||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/address" |  | ||||||
| 	"github.com/yggdrasil-network/yggdrasil-go/src/config" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // Adapter defines the minimum required struct members for an adapter type. This |  | ||||||
| // is now the base type for adapters like tun.go. When implementing a new |  | ||||||
| // adapter type, you should extend the adapter struct with this one and should |  | ||||||
| // call the Adapter.Init() function when initialising. |  | ||||||
| type Adapter struct { |  | ||||||
| 	adapterImplementation |  | ||||||
| 	Core        *Core |  | ||||||
| 	Config      *config.NodeState |  | ||||||
| 	Log         *log.Logger |  | ||||||
| 	Send        chan<- []byte |  | ||||||
| 	Recv        <-chan []byte |  | ||||||
| 	Reject      <-chan RejectedPacket |  | ||||||
| 	Reconfigure chan chan error |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Defines the minimum required functions for an adapter type. Note that the |  | ||||||
| // implementation of Init() should call Adapter.Init(). This is not exported |  | ||||||
| // because doing so breaks the gomobile bindings for iOS/Android. |  | ||||||
| type adapterImplementation interface { |  | ||||||
| 	Init(*config.NodeState, *log.Logger, chan<- []byte, <-chan []byte, <-chan RejectedPacket) |  | ||||||
| 	Name() string |  | ||||||
| 	MTU() int |  | ||||||
| 	IsTAP() bool |  | ||||||
| 	Start(address.Address, address.Subnet) error |  | ||||||
| 	Close() error |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Init initialises the adapter with the necessary channels to operate from the |  | ||||||
| // router. When defining a new Adapter type, the Adapter should call this |  | ||||||
| // function from within it's own Init function to set up the channels. It is |  | ||||||
| // otherwise not expected for you to call this function directly. |  | ||||||
| func (adapter *Adapter) Init(config *config.NodeState, log *log.Logger, send chan<- []byte, recv <-chan []byte, reject <-chan RejectedPacket) { |  | ||||||
| 	adapter.Config = config |  | ||||||
| 	adapter.Log = log |  | ||||||
| 	adapter.Send = send |  | ||||||
| 	adapter.Recv = recv |  | ||||||
| 	adapter.Reject = reject |  | ||||||
| 	adapter.Reconfigure = make(chan chan error, 1) |  | ||||||
| } |  | ||||||
|  | @ -16,7 +16,7 @@ type Conn struct { | ||||||
| 	nodeID        *crypto.NodeID | 	nodeID        *crypto.NodeID | ||||||
| 	nodeMask      *crypto.NodeID | 	nodeMask      *crypto.NodeID | ||||||
| 	session       *sessionInfo | 	session       *sessionInfo | ||||||
| 	sessionMutex  *sync.RWMutex | 	mutex         *sync.RWMutex | ||||||
| 	readDeadline  time.Time | 	readDeadline  time.Time | ||||||
| 	writeDeadline time.Time | 	writeDeadline time.Time | ||||||
| 	expired       bool | 	expired       bool | ||||||
|  | @ -30,9 +30,10 @@ func (c *Conn) startSearch() { | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		if sinfo != nil { | 		if sinfo != nil { | ||||||
| 			c.sessionMutex.Lock() | 			c.mutex.Lock() | ||||||
| 			c.session = sinfo | 			c.session = sinfo | ||||||
| 			c.sessionMutex.Unlock() | 			c.nodeID, c.nodeMask = sinfo.theirAddr.GetNodeIDandMask() | ||||||
|  | 			c.mutex.Unlock() | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	doSearch := func() { | 	doSearch := func() { | ||||||
|  | @ -65,8 +66,8 @@ func (c *Conn) startSearch() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *Conn) Read(b []byte) (int, error) { | func (c *Conn) Read(b []byte) (int, error) { | ||||||
| 	c.sessionMutex.RLock() | 	c.mutex.RLock() | ||||||
| 	defer c.sessionMutex.RUnlock() | 	defer c.mutex.RUnlock() | ||||||
| 	if c.expired { | 	if c.expired { | ||||||
| 		return 0, errors.New("session is closed") | 		return 0, errors.New("session is closed") | ||||||
| 	} | 	} | ||||||
|  | @ -119,8 +120,8 @@ func (c *Conn) Read(b []byte) (int, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *Conn) Write(b []byte) (bytesWritten int, err error) { | func (c *Conn) Write(b []byte) (bytesWritten int, err error) { | ||||||
| 	c.sessionMutex.RLock() | 	c.mutex.RLock() | ||||||
| 	defer c.sessionMutex.RUnlock() | 	defer c.mutex.RUnlock() | ||||||
| 	if c.expired { | 	if c.expired { | ||||||
| 		return 0, errors.New("session is closed") | 		return 0, errors.New("session is closed") | ||||||
| 	} | 	} | ||||||
|  | @ -175,7 +176,9 @@ func (c *Conn) LocalAddr() crypto.NodeID { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *Conn) RemoteAddr() crypto.NodeID { | func (c *Conn) RemoteAddr() crypto.NodeID { | ||||||
| 	return *crypto.GetNodeID(&c.session.theirPermPub) | 	c.mutex.RLock() | ||||||
|  | 	defer c.mutex.RUnlock() | ||||||
|  | 	return *c.nodeID | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *Conn) SetDeadline(t time.Time) error { | func (c *Conn) SetDeadline(t time.Time) error { | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"net" | 	"net" | ||||||
| 	"sync" |  | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/gologme/log" | 	"github.com/gologme/log" | ||||||
|  | @ -77,7 +76,6 @@ func (c *Core) init() error { | ||||||
| 	c.searches.init(c) | 	c.searches.init(c) | ||||||
| 	c.dht.init(c) | 	c.dht.init(c) | ||||||
| 	c.sessions.init(c) | 	c.sessions.init(c) | ||||||
| 	//c.multicast.init(c) |  | ||||||
| 	c.peers.init(c) | 	c.peers.init(c) | ||||||
| 	c.router.init(c) | 	c.router.init(c) | ||||||
| 	c.switchTable.init(c) // TODO move before peers? before router? | 	c.switchTable.init(c) // TODO move before peers? before router? | ||||||
|  | @ -168,21 +166,6 @@ func BuildVersion() string { | ||||||
| 	return buildVersion | 	return buildVersion | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // SetRouterAdapter instructs Yggdrasil to use the given adapter when starting |  | ||||||
| // the router. The adapter must implement the standard |  | ||||||
| // adapter.adapterImplementation interface and should extend the adapter.Adapter |  | ||||||
| // struct. |  | ||||||
| func (c *Core) SetRouterAdapter(adapter interface{}) error { |  | ||||||
| 	// We do this because adapterImplementation is not a valid type for the |  | ||||||
| 	// gomobile bindings so we just ask for a generic interface and try to cast it |  | ||||||
| 	// to adapterImplementation instead |  | ||||||
| 	if a, ok := adapter.(adapterImplementation); ok { |  | ||||||
| 		c.router.adapter = a |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 	return errors.New("unsuitable adapter") |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Start starts up Yggdrasil using the provided config.NodeConfig, and outputs | // Start starts up Yggdrasil using the provided config.NodeConfig, and outputs | ||||||
| // debug logging through the provided log.Logger. The started stack will include | // debug logging through the provided log.Logger. The started stack will include | ||||||
| // TCP and UDP sockets, a multicast discovery socket, an admin socket, router, | // TCP and UDP sockets, a multicast discovery socket, an admin socket, router, | ||||||
|  | @ -233,13 +216,6 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) (*config.NodeState, | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if c.router.adapter != nil { |  | ||||||
| 		if err := c.router.adapter.Start(c.router.addr, c.router.subnet); err != nil { |  | ||||||
| 			c.log.Errorln("Failed to start TUN/TAP") |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	go c.addPeerLoop() | 	go c.addPeerLoop() | ||||||
| 
 | 
 | ||||||
| 	c.log.Infoln("Startup complete") | 	c.log.Infoln("Startup complete") | ||||||
|  | @ -249,14 +225,11 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) (*config.NodeState, | ||||||
| // Stop shuts down the Yggdrasil node. | // Stop shuts down the Yggdrasil node. | ||||||
| func (c *Core) Stop() { | func (c *Core) Stop() { | ||||||
| 	c.log.Infoln("Stopping...") | 	c.log.Infoln("Stopping...") | ||||||
| 	if c.router.adapter != nil { |  | ||||||
| 		c.router.adapter.Close() |  | ||||||
| 	} |  | ||||||
| 	c.admin.close() | 	c.admin.close() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ListenConn returns a listener for Yggdrasil session connections. | // ListenConn returns a listener for Yggdrasil session connections. | ||||||
| func (c *Core) ListenConn() (*Listener, error) { | func (c *Core) ConnListen() (*Listener, error) { | ||||||
| 	c.sessions.listenerMutex.Lock() | 	c.sessions.listenerMutex.Lock() | ||||||
| 	defer c.sessions.listenerMutex.Unlock() | 	defer c.sessions.listenerMutex.Unlock() | ||||||
| 	if c.sessions.listener != nil { | 	if c.sessions.listener != nil { | ||||||
|  | @ -270,40 +243,11 @@ func (c *Core) ListenConn() (*Listener, error) { | ||||||
| 	return c.sessions.listener, nil | 	return c.sessions.listener, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Dial opens a session to the given node. The first paramter should be "nodeid" | // ConnDialer returns a dialer for Yggdrasil session connections. | ||||||
| // and the second parameter should contain a hexadecimal representation of the | func (c *Core) ConnDialer() (*Dialer, error) { | ||||||
| // target node ID. | 	return &Dialer{ | ||||||
| func (c *Core) Dial(network, address string) (Conn, error) { | 		core: c, | ||||||
| 	conn := Conn{ | 	}, nil | ||||||
| 		sessionMutex: &sync.RWMutex{}, |  | ||||||
| 	} |  | ||||||
| 	nodeID := crypto.NodeID{} |  | ||||||
| 	nodeMask := crypto.NodeID{} |  | ||||||
| 	// Process |  | ||||||
| 	switch network { |  | ||||||
| 	case "nodeid": |  | ||||||
| 		// A node ID was provided - we don't need to do anything special with it |  | ||||||
| 		dest, err := hex.DecodeString(address) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return Conn{}, err |  | ||||||
| 		} |  | ||||||
| 		copy(nodeID[:], dest) |  | ||||||
| 		for i := range nodeMask { |  | ||||||
| 			nodeMask[i] = 0xFF |  | ||||||
| 		} |  | ||||||
| 	default: |  | ||||||
| 		// An unexpected address type was given, so give up |  | ||||||
| 		return Conn{}, errors.New("unexpected address type") |  | ||||||
| 	} |  | ||||||
| 	conn.core = c |  | ||||||
| 	conn.nodeID = &nodeID |  | ||||||
| 	conn.nodeMask = &nodeMask |  | ||||||
| 	conn.core.router.doAdmin(func() { |  | ||||||
| 		conn.startSearch() |  | ||||||
| 	}) |  | ||||||
| 	conn.sessionMutex.Lock() |  | ||||||
| 	defer conn.sessionMutex.Unlock() |  | ||||||
| 	return conn, nil |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ListenTCP starts a new TCP listener. The input URI should match that of the | // ListenTCP starts a new TCP listener. The input URI should match that of the | ||||||
|  |  | ||||||
							
								
								
									
										70
									
								
								src/yggdrasil/dialer.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/yggdrasil/dialer.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,70 @@ | ||||||
|  | package yggdrasil | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"encoding/hex" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
|  | 	"sync" | ||||||
|  | 
 | ||||||
|  | 	"github.com/yggdrasil-network/yggdrasil-go/src/crypto" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Dialer represents an Yggdrasil connection dialer. | ||||||
|  | type Dialer struct { | ||||||
|  | 	core *Core | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Dial opens a session to the given node. The first paramter should be "nodeid" | ||||||
|  | // and the second parameter should contain a hexadecimal representation of the | ||||||
|  | // target node ID. | ||||||
|  | func (d *Dialer) Dial(network, address string) (Conn, error) { | ||||||
|  | 	conn := Conn{ | ||||||
|  | 		mutex: &sync.RWMutex{}, | ||||||
|  | 	} | ||||||
|  | 	nodeID := crypto.NodeID{} | ||||||
|  | 	nodeMask := crypto.NodeID{} | ||||||
|  | 	// Process | ||||||
|  | 	switch network { | ||||||
|  | 	case "nodeid": | ||||||
|  | 		// A node ID was provided - we don't need to do anything special with it | ||||||
|  | 		if tokens := strings.Split(address, "/"); len(tokens) == 2 { | ||||||
|  | 			len, err := strconv.Atoi(tokens[1]) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return Conn{}, err | ||||||
|  | 			} | ||||||
|  | 			dest, err := hex.DecodeString(tokens[0]) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return Conn{}, err | ||||||
|  | 			} | ||||||
|  | 			copy(nodeID[:], dest) | ||||||
|  | 			for idx := 0; idx < len; idx++ { | ||||||
|  | 				nodeMask[idx/8] |= 0x80 >> byte(idx%8) | ||||||
|  | 			} | ||||||
|  | 			fmt.Println(nodeID) | ||||||
|  | 			fmt.Println(nodeMask) | ||||||
|  | 		} else { | ||||||
|  | 			dest, err := hex.DecodeString(tokens[0]) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return Conn{}, err | ||||||
|  | 			} | ||||||
|  | 			copy(nodeID[:], dest) | ||||||
|  | 			for i := range nodeMask { | ||||||
|  | 				nodeMask[i] = 0xFF | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	default: | ||||||
|  | 		// An unexpected address type was given, so give up | ||||||
|  | 		return Conn{}, errors.New("unexpected address type") | ||||||
|  | 	} | ||||||
|  | 	conn.core = d.core | ||||||
|  | 	conn.nodeID = &nodeID | ||||||
|  | 	conn.nodeMask = &nodeMask | ||||||
|  | 	conn.core.router.doAdmin(func() { | ||||||
|  | 		conn.startSearch() | ||||||
|  | 	}) | ||||||
|  | 	conn.mutex.Lock() | ||||||
|  | 	defer conn.mutex.Unlock() | ||||||
|  | 	return conn, nil | ||||||
|  | } | ||||||
|  | @ -41,7 +41,6 @@ type router struct { | ||||||
| 	in          <-chan []byte          // packets we received from the network, link to peer's "out" | 	in          <-chan []byte          // packets we received from the network, link to peer's "out" | ||||||
| 	out         func([]byte)           // packets we're sending to the network, link to peer's "in" | 	out         func([]byte)           // packets we're sending to the network, link to peer's "in" | ||||||
| 	toRecv      chan router_recvPacket // packets to handle via recvPacket() | 	toRecv      chan router_recvPacket // packets to handle via recvPacket() | ||||||
| 	adapter     adapterImplementation  // TUN/TAP adapter |  | ||||||
| 	recv        chan<- []byte          // place where the adapter pulls received packets from | 	recv        chan<- []byte          // place where the adapter pulls received packets from | ||||||
| 	send        <-chan []byte          // place where the adapter puts outgoing packets | 	send        <-chan []byte          // place where the adapter puts outgoing packets | ||||||
| 	reject      chan<- RejectedPacket  // place where we send error packets back to adapter | 	reject      chan<- RejectedPacket  // place where we send error packets back to adapter | ||||||
|  | @ -136,9 +135,6 @@ func (r *router) init(core *Core) { | ||||||
| 	r.nodeinfo.setNodeInfo(r.core.config.Current.NodeInfo, r.core.config.Current.NodeInfoPrivacy) | 	r.nodeinfo.setNodeInfo(r.core.config.Current.NodeInfo, r.core.config.Current.NodeInfoPrivacy) | ||||||
| 	r.core.config.Mutex.RUnlock() | 	r.core.config.Mutex.RUnlock() | ||||||
| 	r.cryptokey.init(r.core) | 	r.cryptokey.init(r.core) | ||||||
| 	if r.adapter != nil { |  | ||||||
| 		r.adapter.Init(&r.core.config, r.core.log, send, recv, reject) |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Starts the mainLoop goroutine. | // Starts the mainLoop goroutine. | ||||||
|  |  | ||||||
|  | @ -289,9 +289,7 @@ func (ss *sessions) createSession(theirPermKey *crypto.BoxPubKey) *sessionInfo { | ||||||
| 	sinfo.mySesPriv = *priv | 	sinfo.mySesPriv = *priv | ||||||
| 	sinfo.myNonce = *crypto.NewBoxNonce() | 	sinfo.myNonce = *crypto.NewBoxNonce() | ||||||
| 	sinfo.theirMTU = 1280 | 	sinfo.theirMTU = 1280 | ||||||
| 	if ss.core.router.adapter != nil { | 	sinfo.myMTU = 1280 | ||||||
| 		sinfo.myMTU = uint16(ss.core.router.adapter.MTU()) |  | ||||||
| 	} |  | ||||||
| 	now := time.Now() | 	now := time.Now() | ||||||
| 	sinfo.timeMutex.Lock() | 	sinfo.timeMutex.Lock() | ||||||
| 	sinfo.time = now | 	sinfo.time = now | ||||||
|  | @ -482,7 +480,7 @@ func (ss *sessions) handlePing(ping *sessionPing) { | ||||||
| 			conn := &Conn{ | 			conn := &Conn{ | ||||||
| 				core:     ss.core, | 				core:     ss.core, | ||||||
| 				session:  sinfo, | 				session:  sinfo, | ||||||
| 				sessionMutex: &sync.RWMutex{}, | 				mutex:    &sync.RWMutex{}, | ||||||
| 				nodeID:   crypto.GetNodeID(&sinfo.theirPermPub), | 				nodeID:   crypto.GetNodeID(&sinfo.theirPermPub), | ||||||
| 				nodeMask: &crypto.NodeID{}, | 				nodeMask: &crypto.NodeID{}, | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue