mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03:00 
			
		
		
		
	Refactoring: move tuntap and icmpv6 into separate package
This commit is contained in:
		
							parent
							
								
									67c670ab4c
								
							
						
					
					
						commit
						0b494a8255
					
				
					 20 changed files with 307 additions and 240 deletions
				
			
		| 
						 | 
				
			
			@ -2,11 +2,36 @@ package config
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NodeState represents the active and previous configuration of the node and
 | 
			
		||||
// protects it with a mutex
 | 
			
		||||
type NodeState struct {
 | 
			
		||||
	Current  NodeConfig
 | 
			
		||||
	Previous NodeConfig
 | 
			
		||||
	Mutex    sync.RWMutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get returns both the current and previous node configs
 | 
			
		||||
func (s *NodeState) Get() (NodeConfig, NodeConfig) {
 | 
			
		||||
	s.Mutex.RLock()
 | 
			
		||||
	defer s.Mutex.RUnlock()
 | 
			
		||||
	return s.Current, s.Previous
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Replace the node configuration with new configuration
 | 
			
		||||
func (s *NodeState) Replace(n NodeConfig) NodeConfig {
 | 
			
		||||
	s.Mutex.Lock()
 | 
			
		||||
	defer s.Mutex.Unlock()
 | 
			
		||||
	s.Previous = s.Current
 | 
			
		||||
	s.Current = n
 | 
			
		||||
	return s.Current
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NodeConfig defines all configuration values needed to run a signle yggdrasil node
 | 
			
		||||
type NodeConfig struct {
 | 
			
		||||
	Peers                       []string               `comment:"List of connection strings for outbound peer connections in URI format,\ne.g. tcp://a.b.c.d:e or socks://a.b.c.d:e/f.g.h.i:j. These connections\nwill obey the operating system routing table, therefore you should\nuse this section when you may connect via different interfaces."`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package yggdrasil
 | 
			
		||||
package tuntap
 | 
			
		||||
 | 
			
		||||
// The ICMPv6 module implements functions to easily create ICMPv6
 | 
			
		||||
// packets. These functions, when mixed with the built-in Go IPv6
 | 
			
		||||
| 
						 | 
				
			
			@ -25,8 +25,8 @@ type macAddress [6]byte
 | 
			
		|||
 | 
			
		||||
const len_ETHER = 14
 | 
			
		||||
 | 
			
		||||
type icmpv6 struct {
 | 
			
		||||
	tun      *tunAdapter
 | 
			
		||||
type ICMPv6 struct {
 | 
			
		||||
	tun      *TunAdapter
 | 
			
		||||
	mylladdr net.IP
 | 
			
		||||
	mymac    macAddress
 | 
			
		||||
	peermacs map[address.Address]neighbor
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +59,7 @@ func ipv6Header_Marshal(h *ipv6.Header) ([]byte, error) {
 | 
			
		|||
// Initialises the ICMPv6 module by assigning our link-local IPv6 address and
 | 
			
		||||
// our MAC address. ICMPv6 messages will always appear to originate from these
 | 
			
		||||
// addresses.
 | 
			
		||||
func (i *icmpv6) init(t *tunAdapter) {
 | 
			
		||||
func (i *ICMPv6) Init(t *TunAdapter) {
 | 
			
		||||
	i.tun = t
 | 
			
		||||
	i.peermacs = make(map[address.Address]neighbor)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -69,23 +69,23 @@ func (i *icmpv6) init(t *tunAdapter) {
 | 
			
		|||
	i.mylladdr = net.IP{
 | 
			
		||||
		0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFE}
 | 
			
		||||
	copy(i.mymac[:], i.tun.core.router.addr[:])
 | 
			
		||||
	copy(i.mylladdr[9:], i.tun.core.router.addr[1:])
 | 
			
		||||
	copy(i.mymac[:], i.tun.addr[:])
 | 
			
		||||
	copy(i.mylladdr[9:], i.tun.addr[1:])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parses an incoming ICMPv6 packet. The packet provided may be either an
 | 
			
		||||
// ethernet frame containing an IP packet, or the IP packet alone. This is
 | 
			
		||||
// determined by whether the TUN/TAP adapter is running in TUN (layer 3) or
 | 
			
		||||
// TAP (layer 2) mode.
 | 
			
		||||
func (i *icmpv6) parse_packet(datain []byte) {
 | 
			
		||||
func (i *ICMPv6) ParsePacket(datain []byte) {
 | 
			
		||||
	var response []byte
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	// Parse the frame/packet
 | 
			
		||||
	if i.tun.iface.IsTAP() {
 | 
			
		||||
		response, err = i.parse_packet_tap(datain)
 | 
			
		||||
	if i.tun.IsTAP() {
 | 
			
		||||
		response, err = i.UnmarshalPacketL2(datain)
 | 
			
		||||
	} else {
 | 
			
		||||
		response, err = i.parse_packet_tun(datain, nil)
 | 
			
		||||
		response, err = i.UnmarshalPacket(datain, nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -93,22 +93,22 @@ func (i *icmpv6) parse_packet(datain []byte) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Write the packet to TUN/TAP
 | 
			
		||||
	i.tun.iface.Write(response)
 | 
			
		||||
	i.tun.Send <- response
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unwraps the ethernet headers of an incoming ICMPv6 packet and hands off
 | 
			
		||||
// the IP packet to the parse_packet_tun function for further processing.
 | 
			
		||||
// the IP packet to the ParsePacket function for further processing.
 | 
			
		||||
// A response buffer is also created for the response message, also complete
 | 
			
		||||
// with ethernet headers.
 | 
			
		||||
func (i *icmpv6) parse_packet_tap(datain []byte) ([]byte, error) {
 | 
			
		||||
func (i *ICMPv6) UnmarshalPacketL2(datain []byte) ([]byte, error) {
 | 
			
		||||
	// Ignore non-IPv6 frames
 | 
			
		||||
	if binary.BigEndian.Uint16(datain[12:14]) != uint16(0x86DD) {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Hand over to parse_packet_tun to interpret the IPv6 packet
 | 
			
		||||
	// Hand over to ParsePacket to interpret the IPv6 packet
 | 
			
		||||
	mac := datain[6:12]
 | 
			
		||||
	ipv6packet, err := i.parse_packet_tun(datain[len_ETHER:], &mac)
 | 
			
		||||
	ipv6packet, err := i.UnmarshalPacket(datain[len_ETHER:], &mac)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -130,7 +130,7 @@ func (i *icmpv6) parse_packet_tap(datain []byte) ([]byte, error) {
 | 
			
		|||
// sanity checks on the packet - i.e. is the packet an ICMPv6 packet, does the
 | 
			
		||||
// ICMPv6 message match a known expected type. The relevant handler function
 | 
			
		||||
// is then called and a response packet may be returned.
 | 
			
		||||
func (i *icmpv6) parse_packet_tun(datain []byte, datamac *[]byte) ([]byte, error) {
 | 
			
		||||
func (i *ICMPv6) UnmarshalPacket(datain []byte, datamac *[]byte) ([]byte, error) {
 | 
			
		||||
	// Parse the IPv6 packet headers
 | 
			
		||||
	ipv6Header, err := ipv6.ParseHeader(datain[:ipv6.HeaderLen])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -156,13 +156,13 @@ func (i *icmpv6) parse_packet_tun(datain []byte, datamac *[]byte) ([]byte, error
 | 
			
		|||
	// Check for a supported message type
 | 
			
		||||
	switch icmpv6Header.Type {
 | 
			
		||||
	case ipv6.ICMPTypeNeighborSolicitation:
 | 
			
		||||
		if !i.tun.iface.IsTAP() {
 | 
			
		||||
		if !i.tun.IsTAP() {
 | 
			
		||||
			return nil, errors.New("Ignoring Neighbor Solicitation in TUN mode")
 | 
			
		||||
		}
 | 
			
		||||
		response, err := i.handle_ndp(datain[ipv6.HeaderLen:])
 | 
			
		||||
		response, err := i.HandleNDP(datain[ipv6.HeaderLen:])
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			// Create our ICMPv6 response
 | 
			
		||||
			responsePacket, err := i.create_icmpv6_tun(
 | 
			
		||||
			responsePacket, err := CreateICMPv6(
 | 
			
		||||
				ipv6Header.Src, i.mylladdr,
 | 
			
		||||
				ipv6.ICMPTypeNeighborAdvertisement, 0,
 | 
			
		||||
				&icmp.DefaultMessageBody{Data: response})
 | 
			
		||||
| 
						 | 
				
			
			@ -176,7 +176,7 @@ func (i *icmpv6) parse_packet_tun(datain []byte, datamac *[]byte) ([]byte, error
 | 
			
		|||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	case ipv6.ICMPTypeNeighborAdvertisement:
 | 
			
		||||
		if !i.tun.iface.IsTAP() {
 | 
			
		||||
		if !i.tun.IsTAP() {
 | 
			
		||||
			return nil, errors.New("Ignoring Neighbor Advertisement in TUN mode")
 | 
			
		||||
		}
 | 
			
		||||
		if datamac != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -202,9 +202,9 @@ func (i *icmpv6) parse_packet_tun(datain []byte, datamac *[]byte) ([]byte, error
 | 
			
		|||
// Creates an ICMPv6 packet based on the given icmp.MessageBody and other
 | 
			
		||||
// parameters, complete with ethernet and IP headers, which can be written
 | 
			
		||||
// directly to a TAP adapter.
 | 
			
		||||
func (i *icmpv6) create_icmpv6_tap(dstmac macAddress, dst net.IP, src net.IP, mtype ipv6.ICMPType, mcode int, mbody icmp.MessageBody) ([]byte, error) {
 | 
			
		||||
	// Pass through to create_icmpv6_tun
 | 
			
		||||
	ipv6packet, err := i.create_icmpv6_tun(dst, src, mtype, mcode, mbody)
 | 
			
		||||
func (i *ICMPv6) CreateICMPv6L2(dstmac macAddress, dst net.IP, src net.IP, mtype ipv6.ICMPType, mcode int, mbody icmp.MessageBody) ([]byte, error) {
 | 
			
		||||
	// Pass through to CreateICMPv6
 | 
			
		||||
	ipv6packet, err := CreateICMPv6(dst, src, mtype, mcode, mbody)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -224,9 +224,9 @@ func (i *icmpv6) create_icmpv6_tap(dstmac macAddress, dst net.IP, src net.IP, mt
 | 
			
		|||
 | 
			
		||||
// Creates an ICMPv6 packet based on the given icmp.MessageBody and other
 | 
			
		||||
// parameters, complete with IP headers only, which can be written directly to
 | 
			
		||||
// a TUN adapter, or called directly by the create_icmpv6_tap function when
 | 
			
		||||
// a TUN adapter, or called directly by the CreateICMPv6L2 function when
 | 
			
		||||
// generating a message for TAP adapters.
 | 
			
		||||
func (i *icmpv6) create_icmpv6_tun(dst net.IP, src net.IP, mtype ipv6.ICMPType, mcode int, mbody icmp.MessageBody) ([]byte, error) {
 | 
			
		||||
func CreateICMPv6(dst net.IP, src net.IP, mtype ipv6.ICMPType, mcode int, mbody icmp.MessageBody) ([]byte, error) {
 | 
			
		||||
	// Create the ICMPv6 message
 | 
			
		||||
	icmpMessage := icmp.Message{
 | 
			
		||||
		Type: mtype,
 | 
			
		||||
| 
						 | 
				
			
			@ -265,7 +265,7 @@ func (i *icmpv6) create_icmpv6_tun(dst net.IP, src net.IP, mtype ipv6.ICMPType,
 | 
			
		|||
	return responsePacket, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *icmpv6) create_ndp_tap(dst address.Address) ([]byte, error) {
 | 
			
		||||
func (i *ICMPv6) CreateNDPL2(dst address.Address) ([]byte, error) {
 | 
			
		||||
	// Create the ND payload
 | 
			
		||||
	var payload [28]byte
 | 
			
		||||
	copy(payload[:4], []byte{0x00, 0x00, 0x00, 0x00})
 | 
			
		||||
| 
						 | 
				
			
			@ -287,7 +287,7 @@ func (i *icmpv6) create_ndp_tap(dst address.Address) ([]byte, error) {
 | 
			
		|||
	copy(dstmac[2:6], dstaddr[12:16])
 | 
			
		||||
 | 
			
		||||
	// Create the ND request
 | 
			
		||||
	requestPacket, err := i.create_icmpv6_tap(
 | 
			
		||||
	requestPacket, err := i.CreateICMPv6L2(
 | 
			
		||||
		dstmac, dstaddr[:], i.mylladdr,
 | 
			
		||||
		ipv6.ICMPTypeNeighborSolicitation, 0,
 | 
			
		||||
		&icmp.DefaultMessageBody{Data: payload[:]})
 | 
			
		||||
| 
						 | 
				
			
			@ -305,7 +305,7 @@ func (i *icmpv6) create_ndp_tap(dst address.Address) ([]byte, error) {
 | 
			
		|||
// when the host operating system generates an NDP request for any address in
 | 
			
		||||
// the fd00::/8 range, so that the operating system knows to route that traffic
 | 
			
		||||
// to the Yggdrasil TAP adapter.
 | 
			
		||||
func (i *icmpv6) handle_ndp(in []byte) ([]byte, error) {
 | 
			
		||||
func (i *ICMPv6) HandleNDP(in []byte) ([]byte, error) {
 | 
			
		||||
	// Ignore NDP requests for anything outside of fd00::/8
 | 
			
		||||
	var source address.Address
 | 
			
		||||
	copy(source[:], in[8:])
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package yggdrasil
 | 
			
		||||
package tuntap
 | 
			
		||||
 | 
			
		||||
// This manages the tun driver to send/recv packets to/from applications
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -10,21 +10,29 @@ import (
 | 
			
		|||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/gologme/log"
 | 
			
		||||
 | 
			
		||||
	"github.com/songgao/packets/ethernet"
 | 
			
		||||
	"github.com/yggdrasil-network/water"
 | 
			
		||||
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const tun_IPv6_HEADER_LENGTH = 40
 | 
			
		||||
const tun_ETHER_HEADER_LENGTH = 14
 | 
			
		||||
 | 
			
		||||
// Represents a running TUN/TAP interface.
 | 
			
		||||
type tunAdapter struct {
 | 
			
		||||
	Adapter
 | 
			
		||||
	icmpv6 icmpv6
 | 
			
		||||
type TunAdapter struct {
 | 
			
		||||
	yggdrasil.Adapter
 | 
			
		||||
	addr   address.Address
 | 
			
		||||
	subnet address.Subnet
 | 
			
		||||
	log    *log.Logger
 | 
			
		||||
	config *config.NodeState
 | 
			
		||||
	icmpv6 ICMPv6
 | 
			
		||||
	mtu    int
 | 
			
		||||
	iface  *water.Interface
 | 
			
		||||
	mutex  sync.RWMutex // Protects the below
 | 
			
		||||
| 
						 | 
				
			
			@ -40,20 +48,37 @@ func getSupportedMTU(mtu int) int {
 | 
			
		|||
	return mtu
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get the adapter name
 | 
			
		||||
func (tun *TunAdapter) Name() string {
 | 
			
		||||
	return tun.iface.Name()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get the adapter MTU
 | 
			
		||||
func (tun *TunAdapter) MTU() int {
 | 
			
		||||
	return getSupportedMTU(tun.mtu)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get the adapter mode
 | 
			
		||||
func (tun *TunAdapter) IsTAP() bool {
 | 
			
		||||
	return tun.iface.IsTAP()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Initialises the TUN/TAP adapter.
 | 
			
		||||
func (tun *tunAdapter) init(core *Core, send chan<- []byte, recv <-chan []byte) {
 | 
			
		||||
	tun.Adapter.init(core, send, recv)
 | 
			
		||||
	tun.icmpv6.init(tun)
 | 
			
		||||
func (tun *TunAdapter) Init(config *config.NodeState, log *log.Logger, send chan<- []byte, recv <-chan []byte) {
 | 
			
		||||
	tun.config = config
 | 
			
		||||
	tun.log = log
 | 
			
		||||
	tun.Adapter.Init(config, log, send, recv)
 | 
			
		||||
	tun.icmpv6.Init(tun)
 | 
			
		||||
	go func() {
 | 
			
		||||
		for {
 | 
			
		||||
			e := <-tun.reconfigure
 | 
			
		||||
			tun.core.configMutex.RLock()
 | 
			
		||||
			updated := tun.core.config.IfName != tun.core.configOld.IfName ||
 | 
			
		||||
				tun.core.config.IfTAPMode != tun.core.configOld.IfTAPMode ||
 | 
			
		||||
				tun.core.config.IfMTU != tun.core.configOld.IfMTU
 | 
			
		||||
			tun.core.configMutex.RUnlock()
 | 
			
		||||
			e := <-tun.Reconfigure
 | 
			
		||||
			tun.config.Mutex.RLock()
 | 
			
		||||
			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.core.log.Warnln("Reconfiguring TUN/TAP is not supported yet")
 | 
			
		||||
				tun.log.Warnln("Reconfiguring TUN/TAP is not supported yet")
 | 
			
		||||
				e <- nil
 | 
			
		||||
			} else {
 | 
			
		||||
				e <- nil
 | 
			
		||||
| 
						 | 
				
			
			@ -64,13 +89,18 @@ func (tun *tunAdapter) init(core *Core, send chan<- []byte, recv <-chan []byte)
 | 
			
		|||
 | 
			
		||||
// Starts the setup process for the TUN/TAP adapter, and if successful, starts
 | 
			
		||||
// the read/write goroutines to handle packets on that interface.
 | 
			
		||||
func (tun *tunAdapter) start() error {
 | 
			
		||||
	tun.core.configMutex.RLock()
 | 
			
		||||
	ifname := tun.core.config.IfName
 | 
			
		||||
	iftapmode := tun.core.config.IfTAPMode
 | 
			
		||||
	addr := fmt.Sprintf("%s/%d", net.IP(tun.core.router.addr[:]).String(), 8*len(address.GetPrefix())-1)
 | 
			
		||||
	mtu := tun.core.config.IfMTU
 | 
			
		||||
	tun.core.configMutex.RUnlock()
 | 
			
		||||
func (tun *TunAdapter) Start(a address.Address, s address.Subnet) error {
 | 
			
		||||
	tun.addr = a
 | 
			
		||||
	tun.subnet = s
 | 
			
		||||
	if tun.config == nil {
 | 
			
		||||
		return errors.New("No configuration available to TUN/TAP")
 | 
			
		||||
	}
 | 
			
		||||
	tun.config.Mutex.RLock()
 | 
			
		||||
	ifname := tun.config.Current.IfName
 | 
			
		||||
	iftapmode := tun.config.Current.IfTAPMode
 | 
			
		||||
	addr := fmt.Sprintf("%s/%d", net.IP(tun.addr[:]).String(), 8*len(address.GetPrefix())-1)
 | 
			
		||||
	mtu := tun.config.Current.IfMTU
 | 
			
		||||
	tun.config.Mutex.RUnlock()
 | 
			
		||||
	if ifname != "none" {
 | 
			
		||||
		if err := tun.setup(ifname, iftapmode, addr, mtu); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
| 
						 | 
				
			
			@ -82,15 +112,15 @@ func (tun *tunAdapter) start() error {
 | 
			
		|||
	tun.mutex.Lock()
 | 
			
		||||
	tun.isOpen = true
 | 
			
		||||
	tun.mutex.Unlock()
 | 
			
		||||
	go func() { tun.core.log.Errorln("WARNING: tun.read() exited with error:", tun.read()) }()
 | 
			
		||||
	go func() { tun.core.log.Errorln("WARNING: tun.write() exited with error:", tun.write()) }()
 | 
			
		||||
	go func() { tun.log.Errorln("WARNING: tun.read() exited with error:", tun.Read()) }()
 | 
			
		||||
	go func() { tun.log.Errorln("WARNING: tun.write() exited with error:", tun.Write()) }()
 | 
			
		||||
	if iftapmode {
 | 
			
		||||
		go func() {
 | 
			
		||||
			for {
 | 
			
		||||
				if _, ok := tun.icmpv6.peermacs[tun.core.router.addr]; ok {
 | 
			
		||||
				if _, ok := tun.icmpv6.peermacs[tun.addr]; ok {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				request, err := tun.icmpv6.create_ndp_tap(tun.core.router.addr)
 | 
			
		||||
				request, err := tun.icmpv6.CreateNDPL2(tun.addr)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					panic(err)
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -107,9 +137,9 @@ func (tun *tunAdapter) start() error {
 | 
			
		|||
// 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
 | 
			
		||||
// host operating system.
 | 
			
		||||
func (tun *tunAdapter) write() error {
 | 
			
		||||
func (tun *TunAdapter) Write() error {
 | 
			
		||||
	for {
 | 
			
		||||
		data := <-tun.recv
 | 
			
		||||
		data := <-tun.Recv
 | 
			
		||||
		if tun.iface == nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +162,7 @@ func (tun *tunAdapter) write() error {
 | 
			
		|||
				neigh, known := tun.icmpv6.peermacs[destAddr]
 | 
			
		||||
				known = known && (time.Since(neigh.lastsolicitation).Seconds() < 30)
 | 
			
		||||
				if !known {
 | 
			
		||||
					request, err := tun.icmpv6.create_ndp_tap(destAddr)
 | 
			
		||||
					request, err := tun.icmpv6.CreateNDPL2(destAddr)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						panic(err)
 | 
			
		||||
					}
 | 
			
		||||
| 
						 | 
				
			
			@ -147,21 +177,21 @@ func (tun *tunAdapter) write() error {
 | 
			
		|||
			var peermac macAddress
 | 
			
		||||
			var peerknown bool
 | 
			
		||||
			if data[0]&0xf0 == 0x40 {
 | 
			
		||||
				destAddr = tun.core.router.addr
 | 
			
		||||
				destAddr = tun.addr
 | 
			
		||||
			} else if data[0]&0xf0 == 0x60 {
 | 
			
		||||
				if !bytes.Equal(tun.core.router.addr[:16], destAddr[:16]) && !bytes.Equal(tun.core.router.subnet[:8], destAddr[:8]) {
 | 
			
		||||
					destAddr = tun.core.router.addr
 | 
			
		||||
				if !bytes.Equal(tun.addr[:16], destAddr[:16]) && !bytes.Equal(tun.subnet[:8], destAddr[:8]) {
 | 
			
		||||
					destAddr = tun.addr
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if neighbor, ok := tun.icmpv6.peermacs[destAddr]; ok && neighbor.learned {
 | 
			
		||||
				peermac = neighbor.mac
 | 
			
		||||
				peerknown = true
 | 
			
		||||
			} else if neighbor, ok := tun.icmpv6.peermacs[tun.core.router.addr]; ok && neighbor.learned {
 | 
			
		||||
			} else if neighbor, ok := tun.icmpv6.peermacs[tun.addr]; ok && neighbor.learned {
 | 
			
		||||
				peermac = neighbor.mac
 | 
			
		||||
				peerknown = true
 | 
			
		||||
				sendndp(destAddr)
 | 
			
		||||
			} else {
 | 
			
		||||
				sendndp(tun.core.router.addr)
 | 
			
		||||
				sendndp(tun.addr)
 | 
			
		||||
			}
 | 
			
		||||
			if peerknown {
 | 
			
		||||
				var proto ethernet.Ethertype
 | 
			
		||||
| 
						 | 
				
			
			@ -210,7 +240,7 @@ func (tun *tunAdapter) write() error {
 | 
			
		|||
// is running in TAP mode then the ethernet headers will automatically be
 | 
			
		||||
// processed and stripped if necessary. If an ICMPv6 packet is found, then
 | 
			
		||||
// the relevant helper functions in icmpv6.go are called.
 | 
			
		||||
func (tun *tunAdapter) read() error {
 | 
			
		||||
func (tun *TunAdapter) Read() error {
 | 
			
		||||
	mtu := tun.mtu
 | 
			
		||||
	if tun.iface.IsTAP() {
 | 
			
		||||
		mtu += tun_ETHER_HEADER_LENGTH
 | 
			
		||||
| 
						 | 
				
			
			@ -244,18 +274,18 @@ func (tun *tunAdapter) read() error {
 | 
			
		|||
				// Found an ICMPv6 packet
 | 
			
		||||
				b := make([]byte, n)
 | 
			
		||||
				copy(b, buf)
 | 
			
		||||
				go tun.icmpv6.parse_packet(b)
 | 
			
		||||
				go tun.icmpv6.ParsePacket(b)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		packet := append(util.GetBytes(), buf[o:n]...)
 | 
			
		||||
		tun.send <- packet
 | 
			
		||||
		tun.Send <- packet
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Closes the TUN/TAP adapter. This is only usually called when the Yggdrasil
 | 
			
		||||
// process stops. Typically this operation will happen quickly, but on macOS
 | 
			
		||||
// it can block until a read operation is completed.
 | 
			
		||||
func (tun *tunAdapter) close() error {
 | 
			
		||||
func (tun *TunAdapter) Close() error {
 | 
			
		||||
	tun.mutex.Lock()
 | 
			
		||||
	tun.isOpen = false
 | 
			
		||||
	tun.mutex.Unlock()
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
// +build openbsd freebsd netbsd
 | 
			
		||||
 | 
			
		||||
package yggdrasil
 | 
			
		||||
package tuntap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
| 
						 | 
				
			
			@ -77,7 +77,7 @@ type in6_ifreq_lifetime struct {
 | 
			
		|||
// a system socket and making syscalls to the kernel. This is not refined though
 | 
			
		||||
// and often doesn't work (if at all), therefore if a call fails, it resorts
 | 
			
		||||
// to calling "ifconfig" instead.
 | 
			
		||||
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 {
 | 
			
		||||
	var config water.Config
 | 
			
		||||
	if ifname[:4] == "auto" {
 | 
			
		||||
		ifname = "/dev/tap0"
 | 
			
		||||
| 
						 | 
				
			
			@ -103,7 +103,7 @@ func (tun *tunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int
 | 
			
		|||
	return tun.setupAddress(addr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (tun *tunAdapter) setupAddress(addr string) error {
 | 
			
		||||
func (tun *TunAdapter) setupAddress(addr string) error {
 | 
			
		||||
	var sfd int
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
// +build !mobile
 | 
			
		||||
 | 
			
		||||
package yggdrasil
 | 
			
		||||
package tuntap
 | 
			
		||||
 | 
			
		||||
// The darwin platform specific tun parts
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -16,9 +16,9 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
		tun.core.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}
 | 
			
		||||
	iface, err := water.New(config)
 | 
			
		||||
| 
						 | 
				
			
			@ -64,12 +64,12 @@ type ifreq struct {
 | 
			
		|||
 | 
			
		||||
// Sets the IPv6 address of the utun adapter. On Darwin/macOS this is done using
 | 
			
		||||
// a system socket and making direct syscalls to the kernel.
 | 
			
		||||
func (tun *tunAdapter) setupAddress(addr string) error {
 | 
			
		||||
func (tun *TunAdapter) setupAddress(addr string) error {
 | 
			
		||||
	var fd int
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	if fd, err = unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, 0); err != nil {
 | 
			
		||||
		tun.core.log.Printf("Create AF_SYSTEM socket failed: %v.", err)
 | 
			
		||||
		tun.log.Printf("Create AF_SYSTEM socket failed: %v.", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -98,19 +98,19 @@ func (tun *tunAdapter) setupAddress(addr string) error {
 | 
			
		|||
	copy(ir.ifr_name[:], tun.iface.Name())
 | 
			
		||||
	ir.ifru_mtu = uint32(tun.mtu)
 | 
			
		||||
 | 
			
		||||
	tun.core.log.Infof("Interface name: %s", ar.ifra_name)
 | 
			
		||||
	tun.core.log.Infof("Interface IPv6: %s", addr)
 | 
			
		||||
	tun.core.log.Infof("Interface MTU: %d", ir.ifru_mtu)
 | 
			
		||||
	tun.log.Infof("Interface name: %s", ar.ifra_name)
 | 
			
		||||
	tun.log.Infof("Interface IPv6: %s", addr)
 | 
			
		||||
	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 {
 | 
			
		||||
		err = errno
 | 
			
		||||
		tun.core.log.Errorf("Error in darwin_SIOCAIFADDR_IN6: %v", errno)
 | 
			
		||||
		tun.log.Errorf("Error in darwin_SIOCAIFADDR_IN6: %v", errno)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(unix.SIOCSIFMTU), uintptr(unsafe.Pointer(&ir))); errno != 0 {
 | 
			
		||||
		err = errno
 | 
			
		||||
		tun.core.log.Errorf("Error in SIOCSIFMTU: %v", errno)
 | 
			
		||||
		tun.log.Errorf("Error in SIOCSIFMTU: %v", errno)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,19 +1,19 @@
 | 
			
		|||
// +build mobile
 | 
			
		||||
 | 
			
		||||
package yggdrasil
 | 
			
		||||
package tuntap
 | 
			
		||||
 | 
			
		||||
// This is to catch unsupported platforms
 | 
			
		||||
// If your platform supports tun devices, you could try configuring it manually
 | 
			
		||||
 | 
			
		||||
// Creates the TUN/TAP adapter, if supported by the Water library. Note that
 | 
			
		||||
// no guarantees are made at this point on an unsupported platform.
 | 
			
		||||
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 {
 | 
			
		||||
	tun.mtu = getSupportedMTU(mtu)
 | 
			
		||||
	return tun.setupAddress(addr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
func (tun *tunAdapter) setupAddress(addr string) error {
 | 
			
		||||
func (tun *TunAdapter) setupAddress(addr string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
// +build !mobile
 | 
			
		||||
 | 
			
		||||
package yggdrasil
 | 
			
		||||
package tuntap
 | 
			
		||||
 | 
			
		||||
// The linux platform specific tun parts
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
// Configures the TAP 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 {
 | 
			
		||||
	var config water.Config
 | 
			
		||||
	if iftapmode {
 | 
			
		||||
		config = water.Config{DeviceType: water.TAP}
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +50,7 @@ func (tun *tunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int
 | 
			
		|||
// is used to do this, so there is not a hard requirement on "ip" or "ifconfig"
 | 
			
		||||
// to exist on the system, but this will fail if Netlink is not present in the
 | 
			
		||||
// kernel (it nearly always is).
 | 
			
		||||
func (tun *tunAdapter) setupAddress(addr string) error {
 | 
			
		||||
func (tun *TunAdapter) setupAddress(addr string) error {
 | 
			
		||||
	// Set address
 | 
			
		||||
	var netIF *net.Interface
 | 
			
		||||
	ifces, err := net.Interfaces()
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
// +build !linux,!darwin,!windows,!openbsd,!freebsd,!netbsd,!mobile
 | 
			
		||||
 | 
			
		||||
package yggdrasil
 | 
			
		||||
package tuntap
 | 
			
		||||
 | 
			
		||||
import water "github.com/yggdrasil-network/water"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ import water "github.com/yggdrasil-network/water"
 | 
			
		|||
 | 
			
		||||
// Creates the TUN/TAP adapter, if supported by the Water library. Note that
 | 
			
		||||
// no guarantees are made at this point on an unsupported platform.
 | 
			
		||||
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 {
 | 
			
		||||
	var config water.Config
 | 
			
		||||
	if iftapmode {
 | 
			
		||||
		config = water.Config{DeviceType: water.TAP}
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +27,7 @@ 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
 | 
			
		||||
// 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.core.log.Warnln("Platform not supported, you must set the address of", tun.iface.Name(), "to", addr)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package yggdrasil
 | 
			
		||||
package tuntap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ import (
 | 
			
		|||
// Configures the TAP adapter with the correct IPv6 address and MTU. On Windows
 | 
			
		||||
// we don't make use of a direct operating system API to do this - we instead
 | 
			
		||||
// 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 {
 | 
			
		||||
		tun.core.log.Warnln("TUN mode is not supported on this platform, defaulting to TAP")
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +65,7 @@ func (tun *tunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// Sets the MTU of the TAP adapter.
 | 
			
		||||
func (tun *tunAdapter) setupMTU(mtu int) error {
 | 
			
		||||
func (tun *TunAdapter) setupMTU(mtu int) error {
 | 
			
		||||
	// Set MTU
 | 
			
		||||
	cmd := exec.Command("netsh", "interface", "ipv6", "set", "subinterface",
 | 
			
		||||
		fmt.Sprintf("interface=%s", tun.iface.Name()),
 | 
			
		||||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ func (tun *tunAdapter) setupMTU(mtu int) error {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// Sets the IPv6 address of the TAP adapter.
 | 
			
		||||
func (tun *tunAdapter) setupAddress(addr string) error {
 | 
			
		||||
func (tun *TunAdapter) setupAddress(addr string) error {
 | 
			
		||||
	// Set address
 | 
			
		||||
	cmd := exec.Command("netsh", "interface", "ipv6", "add", "address",
 | 
			
		||||
		fmt.Sprintf("interface=%s", tun.iface.Name()),
 | 
			
		||||
| 
						 | 
				
			
			@ -1,18 +1,36 @@
 | 
			
		|||
package yggdrasil
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gologme/log"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Defines the minimum required struct members for an adapter type (this is
 | 
			
		||||
// now the base type for tunAdapter in tun.go)
 | 
			
		||||
// now the base type for TunAdapter in tun.go)
 | 
			
		||||
type Adapter struct {
 | 
			
		||||
	core        *Core
 | 
			
		||||
	send        chan<- []byte
 | 
			
		||||
	recv        <-chan []byte
 | 
			
		||||
	reconfigure chan chan error
 | 
			
		||||
	adapterImplementation
 | 
			
		||||
	Core        *Core
 | 
			
		||||
	Send        chan<- []byte
 | 
			
		||||
	Recv        <-chan []byte
 | 
			
		||||
	Reconfigure chan chan error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Defines the minimum required functions for an adapter type
 | 
			
		||||
type adapterImplementation interface {
 | 
			
		||||
	Init(*config.NodeState, *log.Logger, chan<- []byte, <-chan []byte)
 | 
			
		||||
	Name() string
 | 
			
		||||
	MTU() int
 | 
			
		||||
	IsTAP() bool
 | 
			
		||||
	Start(address.Address, address.Subnet) error
 | 
			
		||||
	Read() error
 | 
			
		||||
	Write() error
 | 
			
		||||
	Close() error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Initialises the adapter.
 | 
			
		||||
func (adapter *Adapter) init(core *Core, send chan<- []byte, recv <-chan []byte) {
 | 
			
		||||
	adapter.core = core
 | 
			
		||||
	adapter.send = send
 | 
			
		||||
	adapter.recv = recv
 | 
			
		||||
	adapter.reconfigure = make(chan chan error, 1)
 | 
			
		||||
func (adapter Adapter) Init(config *config.NodeState, log *log.Logger, send chan<- []byte, recv <-chan []byte) {
 | 
			
		||||
	adapter.Send = send
 | 
			
		||||
	adapter.Recv = recv
 | 
			
		||||
	adapter.Reconfigure = make(chan chan error, 1)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,6 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TODO: Add authentication
 | 
			
		||||
| 
						 | 
				
			
			@ -58,19 +57,17 @@ func (a *admin) init(c *Core) {
 | 
			
		|||
	go func() {
 | 
			
		||||
		for {
 | 
			
		||||
			e := <-a.reconfigure
 | 
			
		||||
			a.core.configMutex.RLock()
 | 
			
		||||
			if a.core.config.AdminListen != a.core.configOld.AdminListen {
 | 
			
		||||
				a.listenaddr = a.core.config.AdminListen
 | 
			
		||||
			current, previous := a.core.config.Get()
 | 
			
		||||
			if current.AdminListen != previous.AdminListen {
 | 
			
		||||
				a.listenaddr = current.AdminListen
 | 
			
		||||
				a.close()
 | 
			
		||||
				a.start()
 | 
			
		||||
			}
 | 
			
		||||
			a.core.configMutex.RUnlock()
 | 
			
		||||
			e <- nil
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	a.core.configMutex.RLock()
 | 
			
		||||
	a.listenaddr = a.core.config.AdminListen
 | 
			
		||||
	a.core.configMutex.RUnlock()
 | 
			
		||||
	current, _ := a.core.config.Get()
 | 
			
		||||
	a.listenaddr = current.AdminListen
 | 
			
		||||
	a.addHandler("list", []string{}, func(in admin_info) (admin_info, error) {
 | 
			
		||||
		handlers := make(map[string]interface{})
 | 
			
		||||
		for _, handler := range a.handlers {
 | 
			
		||||
| 
						 | 
				
			
			@ -171,47 +168,47 @@ func (a *admin) init(c *Core) {
 | 
			
		|||
			}, errors.New("Failed to remove peer")
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
	a.addHandler("getTunTap", []string{}, func(in admin_info) (r admin_info, e error) {
 | 
			
		||||
		defer func() {
 | 
			
		||||
			if err := recover(); err != nil {
 | 
			
		||||
				r = admin_info{"none": admin_info{}}
 | 
			
		||||
				e = nil
 | 
			
		||||
			}
 | 
			
		||||
		}()
 | 
			
		||||
	/*	a.addHandler("getTunTap", []string{}, func(in admin_info) (r admin_info, e error) {
 | 
			
		||||
			defer func() {
 | 
			
		||||
				if err := recover(); err != nil {
 | 
			
		||||
					r = admin_info{"none": admin_info{}}
 | 
			
		||||
					e = nil
 | 
			
		||||
				}
 | 
			
		||||
			}()
 | 
			
		||||
 | 
			
		||||
		return admin_info{
 | 
			
		||||
			a.core.router.tun.iface.Name(): admin_info{
 | 
			
		||||
				"tap_mode": a.core.router.tun.iface.IsTAP(),
 | 
			
		||||
				"mtu":      a.core.router.tun.mtu,
 | 
			
		||||
			},
 | 
			
		||||
		}, nil
 | 
			
		||||
	})
 | 
			
		||||
	a.addHandler("setTunTap", []string{"name", "[tap_mode]", "[mtu]"}, func(in admin_info) (admin_info, error) {
 | 
			
		||||
		// Set sane defaults
 | 
			
		||||
		iftapmode := defaults.GetDefaults().DefaultIfTAPMode
 | 
			
		||||
		ifmtu := defaults.GetDefaults().DefaultIfMTU
 | 
			
		||||
		// Has TAP mode been specified?
 | 
			
		||||
		if tap, ok := in["tap_mode"]; ok {
 | 
			
		||||
			iftapmode = tap.(bool)
 | 
			
		||||
		}
 | 
			
		||||
		// Check we have enough params for MTU
 | 
			
		||||
		if mtu, ok := in["mtu"]; ok {
 | 
			
		||||
			if mtu.(float64) >= 1280 && ifmtu <= defaults.GetDefaults().MaximumIfMTU {
 | 
			
		||||
				ifmtu = int(in["mtu"].(float64))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		// Start the TUN adapter
 | 
			
		||||
		if err := a.startTunWithMTU(in["name"].(string), iftapmode, ifmtu); err != nil {
 | 
			
		||||
			return admin_info{}, errors.New("Failed to configure adapter")
 | 
			
		||||
		} else {
 | 
			
		||||
			return admin_info{
 | 
			
		||||
				a.core.router.tun.iface.Name(): admin_info{
 | 
			
		||||
					"tap_mode": a.core.router.tun.iface.IsTAP(),
 | 
			
		||||
					"mtu":      ifmtu,
 | 
			
		||||
					"mtu":      a.core.router.tun.mtu,
 | 
			
		||||
				},
 | 
			
		||||
			}, nil
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
		})
 | 
			
		||||
		a.addHandler("setTunTap", []string{"name", "[tap_mode]", "[mtu]"}, func(in admin_info) (admin_info, error) {
 | 
			
		||||
			// Set sane defaults
 | 
			
		||||
			iftapmode := defaults.GetDefaults().DefaultIfTAPMode
 | 
			
		||||
			ifmtu := defaults.GetDefaults().DefaultIfMTU
 | 
			
		||||
			// Has TAP mode been specified?
 | 
			
		||||
			if tap, ok := in["tap_mode"]; ok {
 | 
			
		||||
				iftapmode = tap.(bool)
 | 
			
		||||
			}
 | 
			
		||||
			// Check we have enough params for MTU
 | 
			
		||||
			if mtu, ok := in["mtu"]; ok {
 | 
			
		||||
				if mtu.(float64) >= 1280 && ifmtu <= defaults.GetDefaults().MaximumIfMTU {
 | 
			
		||||
					ifmtu = int(in["mtu"].(float64))
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			// Start the TUN adapter
 | 
			
		||||
			if err := a.startTunWithMTU(in["name"].(string), iftapmode, ifmtu); err != nil {
 | 
			
		||||
				return admin_info{}, errors.New("Failed to configure adapter")
 | 
			
		||||
			} else {
 | 
			
		||||
				return admin_info{
 | 
			
		||||
					a.core.router.tun.iface.Name(): admin_info{
 | 
			
		||||
						"tap_mode": a.core.router.tun.iface.IsTAP(),
 | 
			
		||||
						"mtu":      ifmtu,
 | 
			
		||||
					},
 | 
			
		||||
				}, nil
 | 
			
		||||
			}
 | 
			
		||||
		})*/
 | 
			
		||||
	a.addHandler("getMulticastInterfaces", []string{}, func(in admin_info) (admin_info, error) {
 | 
			
		||||
		var intfs []string
 | 
			
		||||
		for _, v := range a.core.multicast.interfaces() {
 | 
			
		||||
| 
						 | 
				
			
			@ -609,6 +606,7 @@ func (a *admin) removePeer(p string) error {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// startTunWithMTU creates the tun/tap device, sets its address, and sets the MTU to the provided value.
 | 
			
		||||
/*
 | 
			
		||||
func (a *admin) startTunWithMTU(ifname string, iftapmode bool, ifmtu int) error {
 | 
			
		||||
	// Close the TUN first if open
 | 
			
		||||
	_ = a.core.router.tun.close()
 | 
			
		||||
| 
						 | 
				
			
			@ -636,6 +634,7 @@ func (a *admin) startTunWithMTU(ifname string, iftapmode bool, ifmtu int) error
 | 
			
		|||
	go a.core.router.tun.write()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// getData_getSelf returns the self node's info for admin responses.
 | 
			
		||||
func (a *admin) getData_getSelf() *admin_nodeInfo {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,25 +55,24 @@ func (c *cryptokey) init(core *Core) {
 | 
			
		|||
// Configure the CKR routes - this must only ever be called from the router
 | 
			
		||||
// goroutine, e.g. through router.doAdmin
 | 
			
		||||
func (c *cryptokey) configure() error {
 | 
			
		||||
	c.core.configMutex.RLock()
 | 
			
		||||
	defer c.core.configMutex.RUnlock()
 | 
			
		||||
	current, _ := c.core.config.Get()
 | 
			
		||||
 | 
			
		||||
	// Set enabled/disabled state
 | 
			
		||||
	c.setEnabled(c.core.config.TunnelRouting.Enable)
 | 
			
		||||
	c.setEnabled(current.TunnelRouting.Enable)
 | 
			
		||||
 | 
			
		||||
	// Clear out existing routes
 | 
			
		||||
	c.ipv6routes = make([]cryptokey_route, 0)
 | 
			
		||||
	c.ipv4routes = make([]cryptokey_route, 0)
 | 
			
		||||
 | 
			
		||||
	// Add IPv6 routes
 | 
			
		||||
	for ipv6, pubkey := range c.core.config.TunnelRouting.IPv6Destinations {
 | 
			
		||||
	for ipv6, pubkey := range current.TunnelRouting.IPv6Destinations {
 | 
			
		||||
		if err := c.addRoute(ipv6, pubkey); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Add IPv4 routes
 | 
			
		||||
	for ipv4, pubkey := range c.core.config.TunnelRouting.IPv4Destinations {
 | 
			
		||||
	for ipv4, pubkey := range current.TunnelRouting.IPv4Destinations {
 | 
			
		||||
		if err := c.addRoute(ipv4, pubkey); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +84,7 @@ func (c *cryptokey) configure() error {
 | 
			
		|||
 | 
			
		||||
	// Add IPv6 sources
 | 
			
		||||
	c.ipv6sources = make([]net.IPNet, 0)
 | 
			
		||||
	for _, source := range c.core.config.TunnelRouting.IPv6Sources {
 | 
			
		||||
	for _, source := range current.TunnelRouting.IPv6Sources {
 | 
			
		||||
		if err := c.addSourceSubnet(source); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +92,7 @@ func (c *cryptokey) configure() error {
 | 
			
		|||
 | 
			
		||||
	// Add IPv4 sources
 | 
			
		||||
	c.ipv4sources = make([]net.IPNet, 0)
 | 
			
		||||
	for _, source := range c.core.config.TunnelRouting.IPv4Sources {
 | 
			
		||||
	for _, source := range current.TunnelRouting.IPv4Sources {
 | 
			
		||||
		if err := c.addSourceSubnet(source); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,6 @@ import (
 | 
			
		|||
	"encoding/hex"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/gologme/log"
 | 
			
		||||
| 
						 | 
				
			
			@ -29,9 +28,7 @@ type Core struct {
 | 
			
		|||
	// This is the main data structure that holds everything else for a node
 | 
			
		||||
	// We're going to keep our own copy of the provided config - that way we can
 | 
			
		||||
	// guarantee that it will be covered by the mutex
 | 
			
		||||
	config      config.NodeConfig // Active config
 | 
			
		||||
	configOld   config.NodeConfig // Previous config
 | 
			
		||||
	configMutex sync.RWMutex      // Protects both config and configOld
 | 
			
		||||
	config      config.NodeState // Config
 | 
			
		||||
	boxPub      crypto.BoxPubKey
 | 
			
		||||
	boxPriv     crypto.BoxPrivKey
 | 
			
		||||
	sigPub      crypto.SigPubKey
 | 
			
		||||
| 
						 | 
				
			
			@ -57,19 +54,21 @@ func (c *Core) init() error {
 | 
			
		|||
		c.log = log.New(ioutil.Discard, "", 0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	boxPubHex, err := hex.DecodeString(c.config.EncryptionPublicKey)
 | 
			
		||||
	current, _ := c.config.Get()
 | 
			
		||||
 | 
			
		||||
	boxPubHex, err := hex.DecodeString(current.EncryptionPublicKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	boxPrivHex, err := hex.DecodeString(c.config.EncryptionPrivateKey)
 | 
			
		||||
	boxPrivHex, err := hex.DecodeString(current.EncryptionPrivateKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	sigPubHex, err := hex.DecodeString(c.config.SigningPublicKey)
 | 
			
		||||
	sigPubHex, err := hex.DecodeString(current.SigningPublicKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	sigPrivHex, err := hex.DecodeString(c.config.SigningPrivateKey)
 | 
			
		||||
	sigPrivHex, err := hex.DecodeString(current.SigningPrivateKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -97,19 +96,16 @@ func (c *Core) init() error {
 | 
			
		|||
func (c *Core) addPeerLoop() {
 | 
			
		||||
	for {
 | 
			
		||||
		// Get the peers from the config - these could change!
 | 
			
		||||
		c.configMutex.RLock()
 | 
			
		||||
		peers := c.config.Peers
 | 
			
		||||
		interfacepeers := c.config.InterfacePeers
 | 
			
		||||
		c.configMutex.RUnlock()
 | 
			
		||||
		current, _ := c.config.Get()
 | 
			
		||||
 | 
			
		||||
		// Add peers from the Peers section
 | 
			
		||||
		for _, peer := range peers {
 | 
			
		||||
		for _, peer := range current.Peers {
 | 
			
		||||
			c.AddPeer(peer, "")
 | 
			
		||||
			time.Sleep(time.Second)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Add peers from the InterfacePeers section
 | 
			
		||||
		for intf, intfpeers := range interfacepeers {
 | 
			
		||||
		for intf, intfpeers := range current.InterfacePeers {
 | 
			
		||||
			for _, peer := range intfpeers {
 | 
			
		||||
				c.AddPeer(peer, intf)
 | 
			
		||||
				time.Sleep(time.Second)
 | 
			
		||||
| 
						 | 
				
			
			@ -126,10 +122,7 @@ func (c *Core) addPeerLoop() {
 | 
			
		|||
func (c *Core) UpdateConfig(config *config.NodeConfig) {
 | 
			
		||||
	c.log.Infoln("Reloading configuration...")
 | 
			
		||||
 | 
			
		||||
	c.configMutex.Lock()
 | 
			
		||||
	c.configOld = c.config
 | 
			
		||||
	c.config = *config
 | 
			
		||||
	c.configMutex.Unlock()
 | 
			
		||||
	c.config.Replace(*config)
 | 
			
		||||
 | 
			
		||||
	errors := 0
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +133,7 @@ func (c *Core) UpdateConfig(config *config.NodeConfig) {
 | 
			
		|||
		c.sessions.reconfigure,
 | 
			
		||||
		c.peers.reconfigure,
 | 
			
		||||
		c.router.reconfigure,
 | 
			
		||||
		c.router.tun.reconfigure,
 | 
			
		||||
		//c.router.tun.Reconfigure,
 | 
			
		||||
		c.router.cryptokey.reconfigure,
 | 
			
		||||
		c.switchTable.reconfigure,
 | 
			
		||||
		c.link.reconfigure,
 | 
			
		||||
| 
						 | 
				
			
			@ -181,13 +174,23 @@ func GetBuildVersion() string {
 | 
			
		|||
	return buildVersion
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Starts up Yggdrasil using the provided NodeConfig, and outputs debug logging
 | 
			
		||||
// Set the router adapter
 | 
			
		||||
func (c *Core) SetRouterAdapter(adapter adapterImplementation) {
 | 
			
		||||
	c.router.tun = adapter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Starts up Yggdrasil using the provided NodeState, and outputs debug logging
 | 
			
		||||
// through the provided log.Logger. The started stack will include TCP and UDP
 | 
			
		||||
// sockets, a multicast discovery socket, an admin socket, router, switch and
 | 
			
		||||
// DHT node.
 | 
			
		||||
func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
 | 
			
		||||
	c.log = log
 | 
			
		||||
 | 
			
		||||
	c.config = config.NodeState{
 | 
			
		||||
		Current:  *nc,
 | 
			
		||||
		Previous: *nc,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if name := GetBuildName(); name != "unknown" {
 | 
			
		||||
		c.log.Infoln("Build name:", name)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -197,11 +200,6 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
 | 
			
		|||
 | 
			
		||||
	c.log.Infoln("Starting up...")
 | 
			
		||||
 | 
			
		||||
	c.configMutex.Lock()
 | 
			
		||||
	c.config = *nc
 | 
			
		||||
	c.configOld = c.config
 | 
			
		||||
	c.configMutex.Unlock()
 | 
			
		||||
 | 
			
		||||
	c.init()
 | 
			
		||||
 | 
			
		||||
	if err := c.link.init(c); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -209,9 +207,11 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
 | 
			
		|||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if nc.SwitchOptions.MaxTotalQueueSize >= SwitchQueueTotalMinSize {
 | 
			
		||||
		c.switchTable.queueTotalMaxSize = nc.SwitchOptions.MaxTotalQueueSize
 | 
			
		||||
	c.config.Mutex.RLock()
 | 
			
		||||
	if c.config.Current.SwitchOptions.MaxTotalQueueSize >= SwitchQueueTotalMinSize {
 | 
			
		||||
		c.switchTable.queueTotalMaxSize = c.config.Current.SwitchOptions.MaxTotalQueueSize
 | 
			
		||||
	}
 | 
			
		||||
	c.config.Mutex.RUnlock()
 | 
			
		||||
 | 
			
		||||
	if err := c.switchTable.start(); err != nil {
 | 
			
		||||
		c.log.Errorln("Failed to start switch")
 | 
			
		||||
| 
						 | 
				
			
			@ -233,7 +233,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
 | 
			
		|||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := c.router.tun.start(); err != nil {
 | 
			
		||||
	if err := c.router.tun.Start(c.router.addr, c.router.subnet); err != nil {
 | 
			
		||||
		c.log.Errorln("Failed to start TUN/TAP")
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -247,7 +247,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
 | 
			
		|||
// Stops the Yggdrasil node.
 | 
			
		||||
func (c *Core) Stop() {
 | 
			
		||||
	c.log.Infoln("Stopping...")
 | 
			
		||||
	c.router.tun.close()
 | 
			
		||||
	c.router.tun.Close()
 | 
			
		||||
	c.admin.close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -343,10 +343,12 @@ func (c *Core) GetTUNDefaultIfTAPMode() bool {
 | 
			
		|||
 | 
			
		||||
// Gets the current TUN/TAP interface name.
 | 
			
		||||
func (c *Core) GetTUNIfName() string {
 | 
			
		||||
	return c.router.tun.iface.Name()
 | 
			
		||||
	//return c.router.tun.iface.Name()
 | 
			
		||||
	return c.router.tun.Name()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Gets the current TUN/TAP interface MTU.
 | 
			
		||||
func (c *Core) GetTUNIfMTU() int {
 | 
			
		||||
	return c.router.tun.mtu
 | 
			
		||||
	//return c.router.tun.mtu
 | 
			
		||||
	return c.router.tun.MTU()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,9 +23,8 @@ func (m *multicast) init(core *Core) {
 | 
			
		|||
	m.core = core
 | 
			
		||||
	m.reconfigure = make(chan chan error, 1)
 | 
			
		||||
	m.listeners = make(map[string]*tcpListener)
 | 
			
		||||
	m.core.configMutex.RLock()
 | 
			
		||||
	m.listenPort = m.core.config.LinkLocalTCPPort
 | 
			
		||||
	m.core.configMutex.RUnlock()
 | 
			
		||||
	current, _ := m.core.config.Get()
 | 
			
		||||
	m.listenPort = current.LinkLocalTCPPort
 | 
			
		||||
	go func() {
 | 
			
		||||
		for {
 | 
			
		||||
			e := <-m.reconfigure
 | 
			
		||||
| 
						 | 
				
			
			@ -70,9 +69,8 @@ func (m *multicast) start() error {
 | 
			
		|||
 | 
			
		||||
func (m *multicast) interfaces() map[string]net.Interface {
 | 
			
		||||
	// Get interface expressions from config
 | 
			
		||||
	m.core.configMutex.RLock()
 | 
			
		||||
	exprs := m.core.config.MulticastInterfaces
 | 
			
		||||
	m.core.configMutex.RUnlock()
 | 
			
		||||
	current, _ := m.core.config.Get()
 | 
			
		||||
	exprs := current.MulticastInterfaces
 | 
			
		||||
	// Ask the system for network interfaces
 | 
			
		||||
	interfaces := make(map[string]net.Interface)
 | 
			
		||||
	allifaces, err := net.Interfaces()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,42 +44,42 @@ func (ps *peers) init(c *Core) {
 | 
			
		|||
// because the key is in the whitelist or because the whitelist is empty.
 | 
			
		||||
func (ps *peers) isAllowedEncryptionPublicKey(box *crypto.BoxPubKey) bool {
 | 
			
		||||
	boxstr := hex.EncodeToString(box[:])
 | 
			
		||||
	ps.core.configMutex.RLock()
 | 
			
		||||
	defer ps.core.configMutex.RUnlock()
 | 
			
		||||
	for _, v := range ps.core.config.AllowedEncryptionPublicKeys {
 | 
			
		||||
	ps.core.config.Mutex.RLock()
 | 
			
		||||
	defer ps.core.config.Mutex.RUnlock()
 | 
			
		||||
	for _, v := range ps.core.config.Current.AllowedEncryptionPublicKeys {
 | 
			
		||||
		if v == boxstr {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return len(ps.core.config.AllowedEncryptionPublicKeys) == 0
 | 
			
		||||
	return len(ps.core.config.Current.AllowedEncryptionPublicKeys) == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Adds a key to the whitelist.
 | 
			
		||||
func (ps *peers) addAllowedEncryptionPublicKey(box string) {
 | 
			
		||||
	ps.core.configMutex.RLock()
 | 
			
		||||
	defer ps.core.configMutex.RUnlock()
 | 
			
		||||
	ps.core.config.AllowedEncryptionPublicKeys =
 | 
			
		||||
		append(ps.core.config.AllowedEncryptionPublicKeys, box)
 | 
			
		||||
	ps.core.config.Mutex.RLock()
 | 
			
		||||
	defer ps.core.config.Mutex.RUnlock()
 | 
			
		||||
	ps.core.config.Current.AllowedEncryptionPublicKeys =
 | 
			
		||||
		append(ps.core.config.Current.AllowedEncryptionPublicKeys, box)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Removes a key from the whitelist.
 | 
			
		||||
func (ps *peers) removeAllowedEncryptionPublicKey(box string) {
 | 
			
		||||
	ps.core.configMutex.RLock()
 | 
			
		||||
	defer ps.core.configMutex.RUnlock()
 | 
			
		||||
	for k, v := range ps.core.config.AllowedEncryptionPublicKeys {
 | 
			
		||||
	ps.core.config.Mutex.RLock()
 | 
			
		||||
	defer ps.core.config.Mutex.RUnlock()
 | 
			
		||||
	for k, v := range ps.core.config.Current.AllowedEncryptionPublicKeys {
 | 
			
		||||
		if v == box {
 | 
			
		||||
			ps.core.config.AllowedEncryptionPublicKeys =
 | 
			
		||||
				append(ps.core.config.AllowedEncryptionPublicKeys[:k],
 | 
			
		||||
					ps.core.config.AllowedEncryptionPublicKeys[k+1:]...)
 | 
			
		||||
			ps.core.config.Current.AllowedEncryptionPublicKeys =
 | 
			
		||||
				append(ps.core.config.Current.AllowedEncryptionPublicKeys[:k],
 | 
			
		||||
					ps.core.config.Current.AllowedEncryptionPublicKeys[k+1:]...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Gets the whitelist of allowed keys for incoming connections.
 | 
			
		||||
func (ps *peers) getAllowedEncryptionPublicKeys() []string {
 | 
			
		||||
	ps.core.configMutex.RLock()
 | 
			
		||||
	defer ps.core.configMutex.RUnlock()
 | 
			
		||||
	return ps.core.config.AllowedEncryptionPublicKeys
 | 
			
		||||
	ps.core.config.Mutex.RLock()
 | 
			
		||||
	defer ps.core.config.Mutex.RUnlock()
 | 
			
		||||
	return ps.core.config.Current.AllowedEncryptionPublicKeys
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Atomically gets a map[switchPort]*peer of known peers.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,9 +26,6 @@ import (
 | 
			
		|||
	"bytes"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/net/icmp"
 | 
			
		||||
	"golang.org/x/net/ipv6"
 | 
			
		||||
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
			
		||||
| 
						 | 
				
			
			@ -44,8 +41,7 @@ type router struct {
 | 
			
		|||
	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"
 | 
			
		||||
	toRecv      chan router_recvPacket // packets to handle via recvPacket()
 | 
			
		||||
	tun         tunAdapter             // TUN/TAP adapter
 | 
			
		||||
	adapters    []Adapter              // Other adapters
 | 
			
		||||
	tun         adapterImplementation  // TUN/TAP adapter
 | 
			
		||||
	recv        chan<- []byte          // place where the tun pulls received packets from
 | 
			
		||||
	send        <-chan []byte          // place where the tun puts outgoing packets
 | 
			
		||||
	reset       chan struct{}          // signal that coords changed (re-init sessions/dht)
 | 
			
		||||
| 
						 | 
				
			
			@ -112,11 +108,11 @@ func (r *router) init(core *Core) {
 | 
			
		|||
	r.reset = make(chan struct{}, 1)
 | 
			
		||||
	r.admin = make(chan func(), 32)
 | 
			
		||||
	r.nodeinfo.init(r.core)
 | 
			
		||||
	r.core.configMutex.RLock()
 | 
			
		||||
	r.nodeinfo.setNodeInfo(r.core.config.NodeInfo, r.core.config.NodeInfoPrivacy)
 | 
			
		||||
	r.core.configMutex.RUnlock()
 | 
			
		||||
	r.core.config.Mutex.RLock()
 | 
			
		||||
	r.nodeinfo.setNodeInfo(r.core.config.Current.NodeInfo, r.core.config.Current.NodeInfoPrivacy)
 | 
			
		||||
	r.core.config.Mutex.RUnlock()
 | 
			
		||||
	r.cryptokey.init(r.core)
 | 
			
		||||
	r.tun.init(r.core, send, recv)
 | 
			
		||||
	r.tun.Init(&r.core.config, r.core.log, send, recv)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Starts the mainLoop goroutine.
 | 
			
		||||
| 
						 | 
				
			
			@ -157,9 +153,8 @@ func (r *router) mainLoop() {
 | 
			
		|||
		case f := <-r.admin:
 | 
			
		||||
			f()
 | 
			
		||||
		case e := <-r.reconfigure:
 | 
			
		||||
			r.core.configMutex.RLock()
 | 
			
		||||
			e <- r.nodeinfo.setNodeInfo(r.core.config.NodeInfo, r.core.config.NodeInfoPrivacy)
 | 
			
		||||
			r.core.configMutex.RUnlock()
 | 
			
		||||
			current, _ := r.core.config.Get()
 | 
			
		||||
			e <- r.nodeinfo.setNodeInfo(current.NodeInfo, current.NodeInfoPrivacy)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -308,7 +303,7 @@ func (r *router) sendPacket(bs []byte) {
 | 
			
		|||
		// Generate an ICMPv6 Packet Too Big for packets larger than session MTU
 | 
			
		||||
		if len(bs) > int(sinfo.getMTU()) {
 | 
			
		||||
			// Get the size of the oversized payload, up to a max of 900 bytes
 | 
			
		||||
			window := 900
 | 
			
		||||
			/*window := 900
 | 
			
		||||
			if int(sinfo.getMTU()) < window {
 | 
			
		||||
				window = int(sinfo.getMTU())
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -320,12 +315,12 @@ func (r *router) sendPacket(bs []byte) {
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			// Create the ICMPv6 response from it
 | 
			
		||||
			icmpv6Buf, err := r.tun.icmpv6.create_icmpv6_tun(
 | 
			
		||||
			icmpv6Buf, err := CreateICMPv6(
 | 
			
		||||
				bs[8:24], bs[24:40],
 | 
			
		||||
				ipv6.ICMPTypePacketTooBig, 0, ptb)
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				r.recv <- icmpv6Buf
 | 
			
		||||
			}
 | 
			
		||||
			}*/
 | 
			
		||||
 | 
			
		||||
			// Don't continue - drop the packet
 | 
			
		||||
			return
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -148,17 +148,17 @@ func (ss *sessions) init(core *Core) {
 | 
			
		|||
 | 
			
		||||
// Determines whether the session firewall is enabled.
 | 
			
		||||
func (ss *sessions) isSessionFirewallEnabled() bool {
 | 
			
		||||
	ss.core.configMutex.RLock()
 | 
			
		||||
	defer ss.core.configMutex.RUnlock()
 | 
			
		||||
	ss.core.config.Mutex.RLock()
 | 
			
		||||
	defer ss.core.config.Mutex.RUnlock()
 | 
			
		||||
 | 
			
		||||
	return ss.core.config.SessionFirewall.Enable
 | 
			
		||||
	return ss.core.config.Current.SessionFirewall.Enable
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Determines whether the session with a given publickey is allowed based on
 | 
			
		||||
// session firewall rules.
 | 
			
		||||
func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) bool {
 | 
			
		||||
	ss.core.configMutex.RLock()
 | 
			
		||||
	defer ss.core.configMutex.RUnlock()
 | 
			
		||||
	ss.core.config.Mutex.RLock()
 | 
			
		||||
	defer ss.core.config.Mutex.RUnlock()
 | 
			
		||||
 | 
			
		||||
	// Allow by default if the session firewall is disabled
 | 
			
		||||
	if !ss.isSessionFirewallEnabled() {
 | 
			
		||||
| 
						 | 
				
			
			@ -167,7 +167,7 @@ func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) b
 | 
			
		|||
	// Prepare for checking whitelist/blacklist
 | 
			
		||||
	var box crypto.BoxPubKey
 | 
			
		||||
	// Reject blacklisted nodes
 | 
			
		||||
	for _, b := range ss.core.config.SessionFirewall.BlacklistEncryptionPublicKeys {
 | 
			
		||||
	for _, b := range ss.core.config.Current.SessionFirewall.BlacklistEncryptionPublicKeys {
 | 
			
		||||
		key, err := hex.DecodeString(b)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			copy(box[:crypto.BoxPubKeyLen], key)
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +177,7 @@ func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) b
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// Allow whitelisted nodes
 | 
			
		||||
	for _, b := range ss.core.config.SessionFirewall.WhitelistEncryptionPublicKeys {
 | 
			
		||||
	for _, b := range ss.core.config.Current.SessionFirewall.WhitelistEncryptionPublicKeys {
 | 
			
		||||
		key, err := hex.DecodeString(b)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			copy(box[:crypto.BoxPubKeyLen], key)
 | 
			
		||||
| 
						 | 
				
			
			@ -187,7 +187,7 @@ func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) b
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// Allow outbound sessions if appropriate
 | 
			
		||||
	if ss.core.config.SessionFirewall.AlwaysAllowOutbound {
 | 
			
		||||
	if ss.core.config.Current.SessionFirewall.AlwaysAllowOutbound {
 | 
			
		||||
		if initiator {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -201,11 +201,11 @@ func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) b
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// Allow direct peers if appropriate
 | 
			
		||||
	if ss.core.config.SessionFirewall.AllowFromDirect && isDirectPeer {
 | 
			
		||||
	if ss.core.config.Current.SessionFirewall.AllowFromDirect && isDirectPeer {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	// Allow remote nodes if appropriate
 | 
			
		||||
	if ss.core.config.SessionFirewall.AllowFromRemote && !isDirectPeer {
 | 
			
		||||
	if ss.core.config.Current.SessionFirewall.AllowFromRemote && !isDirectPeer {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	// Finally, default-deny if not matching any of the above rules
 | 
			
		||||
| 
						 | 
				
			
			@ -277,7 +277,7 @@ func (ss *sessions) createSession(theirPermKey *crypto.BoxPubKey) *sessionInfo {
 | 
			
		|||
	sinfo.mySesPriv = *priv
 | 
			
		||||
	sinfo.myNonce = *crypto.NewBoxNonce()
 | 
			
		||||
	sinfo.theirMTU = 1280
 | 
			
		||||
	sinfo.myMTU = uint16(ss.core.router.tun.mtu)
 | 
			
		||||
	sinfo.myMTU = uint16(ss.core.router.tun.MTU())
 | 
			
		||||
	now := time.Now()
 | 
			
		||||
	sinfo.time = now
 | 
			
		||||
	sinfo.mtuTime = now
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -188,9 +188,7 @@ func (t *switchTable) init(core *Core) {
 | 
			
		|||
	now := time.Now()
 | 
			
		||||
	t.core = core
 | 
			
		||||
	t.reconfigure = make(chan chan error, 1)
 | 
			
		||||
	t.core.configMutex.RLock()
 | 
			
		||||
	t.key = t.core.sigPub
 | 
			
		||||
	t.core.configMutex.RUnlock()
 | 
			
		||||
	locator := switchLocator{root: t.key, tstamp: now.Unix()}
 | 
			
		||||
	peers := make(map[switchPort]peerInfo)
 | 
			
		||||
	t.data = switchData{locator: locator, peers: peers}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,10 +82,10 @@ func (t *tcp) init(l *link) error {
 | 
			
		|||
	go func() {
 | 
			
		||||
		for {
 | 
			
		||||
			e := <-t.reconfigure
 | 
			
		||||
			t.link.core.configMutex.RLock()
 | 
			
		||||
			added := util.Difference(t.link.core.config.Listen, t.link.core.configOld.Listen)
 | 
			
		||||
			deleted := util.Difference(t.link.core.configOld.Listen, t.link.core.config.Listen)
 | 
			
		||||
			t.link.core.configMutex.RUnlock()
 | 
			
		||||
			t.link.core.config.Mutex.RLock()
 | 
			
		||||
			added := util.Difference(t.link.core.config.Current.Listen, t.link.core.config.Previous.Listen)
 | 
			
		||||
			deleted := util.Difference(t.link.core.config.Previous.Listen, t.link.core.config.Current.Listen)
 | 
			
		||||
			t.link.core.config.Mutex.RUnlock()
 | 
			
		||||
			if len(added) > 0 || len(deleted) > 0 {
 | 
			
		||||
				for _, a := range added {
 | 
			
		||||
					if a[:6] != "tcp://" {
 | 
			
		||||
| 
						 | 
				
			
			@ -115,9 +115,9 @@ func (t *tcp) init(l *link) error {
 | 
			
		|||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	t.link.core.configMutex.RLock()
 | 
			
		||||
	defer t.link.core.configMutex.RUnlock()
 | 
			
		||||
	for _, listenaddr := range t.link.core.config.Listen {
 | 
			
		||||
	t.link.core.config.Mutex.RLock()
 | 
			
		||||
	defer t.link.core.config.Mutex.RUnlock()
 | 
			
		||||
	for _, listenaddr := range t.link.core.config.Current.Listen {
 | 
			
		||||
		if listenaddr[:6] != "tcp://" {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue