mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 03:05:07 +03:00 
			
		
		
		
	Merge pull request #401 from neilalexander/modular
Refactoring for Yggdrasil library
This commit is contained in:
		
						commit
						24fa8355f1
					
				
					 36 changed files with 1135 additions and 848 deletions
				
			
		| 
						 | 
					@ -24,11 +24,11 @@ jobs:
 | 
				
			||||||
          command: |
 | 
					          command: |
 | 
				
			||||||
              sudo apt-get install -y alien
 | 
					              sudo apt-get install -y alien
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - run:
 | 
					    #  - run:
 | 
				
			||||||
          name: Test debug builds
 | 
					    #      name: Test debug builds
 | 
				
			||||||
          command: |
 | 
					    #      command: |
 | 
				
			||||||
              ./build -d
 | 
					    #          ./build -d
 | 
				
			||||||
              test -f yggdrasil && test -f yggdrasilctl
 | 
					    #          test -f yggdrasil && test -f yggdrasilctl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - run:
 | 
					      - run:
 | 
				
			||||||
          name: Build for Linux (including Debian packages and RPMs)
 | 
					          name: Build for Linux (including Debian packages and RPMs)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								build
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								build
									
										
									
									
									
								
							| 
						 | 
					@ -28,10 +28,16 @@ fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [ $IOS ]; then
 | 
					if [ $IOS ]; then
 | 
				
			||||||
  echo "Building framework for iOS"
 | 
					  echo "Building framework for iOS"
 | 
				
			||||||
  gomobile bind -target ios -tags mobile -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil
 | 
					  gomobile bind -target ios -tags mobile -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" \
 | 
				
			||||||
 | 
					    github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil \
 | 
				
			||||||
 | 
					    github.com/yggdrasil-network/yggdrasil-go/src/mobile \
 | 
				
			||||||
 | 
					    github.com/yggdrasil-network/yggdrasil-go/src/config
 | 
				
			||||||
elif [ $ANDROID ]; then
 | 
					elif [ $ANDROID ]; then
 | 
				
			||||||
  echo "Building aar for Android"
 | 
					  echo "Building aar for Android"
 | 
				
			||||||
  gomobile bind -target android -tags mobile -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil
 | 
					  gomobile bind -target android -tags mobile -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" \
 | 
				
			||||||
 | 
					    github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil \
 | 
				
			||||||
 | 
					    github.com/yggdrasil-network/yggdrasil-go/src/mobile \
 | 
				
			||||||
 | 
					    github.com/yggdrasil-network/yggdrasil-go/src/config
 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
  for CMD in `ls cmd/` ; do
 | 
					  for CMD in `ls cmd/` ; do
 | 
				
			||||||
    echo "Building: $CMD"
 | 
					    echo "Building: $CMD"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,8 @@ import (
 | 
				
			||||||
	"github.com/mitchellh/mapstructure"
 | 
						"github.com/mitchellh/mapstructure"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
				
			||||||
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
 | 
				
			||||||
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/tuntap"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +28,9 @@ type nodeConfig = config.NodeConfig
 | 
				
			||||||
type Core = yggdrasil.Core
 | 
					type Core = yggdrasil.Core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type node struct {
 | 
					type node struct {
 | 
				
			||||||
	core Core
 | 
						core      Core
 | 
				
			||||||
 | 
						tuntap    tuntap.TunAdapter
 | 
				
			||||||
 | 
						multicast multicast.Multicast
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *nodeConfig {
 | 
					func readConfig(useconf *bool, useconffile *string, normaliseconf *bool) *nodeConfig {
 | 
				
			||||||
| 
						 | 
					@ -185,8 +189,8 @@ func main() {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	switch {
 | 
						switch {
 | 
				
			||||||
	case *version:
 | 
						case *version:
 | 
				
			||||||
		fmt.Println("Build name:", yggdrasil.GetBuildName())
 | 
							fmt.Println("Build name:", yggdrasil.BuildName())
 | 
				
			||||||
		fmt.Println("Build version:", yggdrasil.GetBuildVersion())
 | 
							fmt.Println("Build version:", yggdrasil.BuildVersion())
 | 
				
			||||||
		os.Exit(0)
 | 
							os.Exit(0)
 | 
				
			||||||
	case *autoconf:
 | 
						case *autoconf:
 | 
				
			||||||
		// Use an autoconf-generated config, this will give us random keys and
 | 
							// Use an autoconf-generated config, this will give us random keys and
 | 
				
			||||||
| 
						 | 
					@ -244,13 +248,20 @@ 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{}
 | 
				
			||||||
	// Now that we have a working configuration, we can now actually start
 | 
						// Before we start the node, set the TUN/TAP to be our router adapter
 | 
				
			||||||
	// Yggdrasil. This will start the router, switch, DHT node, TCP and UDP
 | 
						n.core.SetRouterAdapter(&n.tuntap)
 | 
				
			||||||
	// sockets, TUN/TAP adapter and multicast discovery port.
 | 
						// Now start Yggdrasil - this starts the DHT, router, switch and other core
 | 
				
			||||||
	if err := n.core.Start(cfg, logger); err != nil {
 | 
						// components needed for Yggdrasil to operate
 | 
				
			||||||
 | 
						state, err := n.core.Start(cfg, logger)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
		logger.Errorln("An error occurred during startup")
 | 
							logger.Errorln("An error occurred during startup")
 | 
				
			||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// Start the multicast interface
 | 
				
			||||||
 | 
						n.multicast.Init(&n.core, state, logger, nil)
 | 
				
			||||||
 | 
						if err := n.multicast.Start(); err != nil {
 | 
				
			||||||
 | 
							logger.Errorln("An error occurred starting multicast:", 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() {
 | 
				
			||||||
| 
						 | 
					@ -258,8 +269,8 @@ 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.GetAddress()
 | 
						address := n.core.Address()
 | 
				
			||||||
	subnet := n.core.GetSubnet()
 | 
						subnet := n.core.Subnet()
 | 
				
			||||||
	logger.Infof("Your IPv6 address is %s", address.String())
 | 
						logger.Infof("Your IPv6 address is %s", address.String())
 | 
				
			||||||
	logger.Infof("Your IPv6 subnet is %s", subnet.String())
 | 
						logger.Infof("Your IPv6 subnet is %s", subnet.String())
 | 
				
			||||||
	// Catch interrupts from the operating system to exit gracefully.
 | 
						// Catch interrupts from the operating system to exit gracefully.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,11 +2,37 @@ package config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
 | 
						"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. This method returns
 | 
				
			||||||
 | 
					// both the new and the previous node configs
 | 
				
			||||||
 | 
					func (s *NodeState) Replace(n NodeConfig) (NodeConfig, NodeConfig) {
 | 
				
			||||||
 | 
						s.Mutex.Lock()
 | 
				
			||||||
 | 
						defer s.Mutex.Unlock()
 | 
				
			||||||
 | 
						s.Previous = s.Current
 | 
				
			||||||
 | 
						s.Current = n
 | 
				
			||||||
 | 
						return s.Current, s.Previous
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NodeConfig defines all configuration values needed to run a signle yggdrasil node
 | 
					// NodeConfig defines all configuration values needed to run a signle yggdrasil node
 | 
				
			||||||
type NodeConfig struct {
 | 
					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."`
 | 
						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."`
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										61
									
								
								src/dummy/dummy.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/dummy/dummy.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,61 @@
 | 
				
			||||||
 | 
					package dummy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gologme/log"
 | 
				
			||||||
 | 
						"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"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DummyAdapter is a non-specific adapter that is used by the mobile APIs.
 | 
				
			||||||
 | 
					// You can also use it to send or receive custom traffic over Yggdrasil.
 | 
				
			||||||
 | 
					type DummyAdapter struct {
 | 
				
			||||||
 | 
						yggdrasil.Adapter
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Init initialises the dummy adapter.
 | 
				
			||||||
 | 
					func (m *DummyAdapter) Init(config *config.NodeState, log *log.Logger, send chan<- []byte, recv <-chan []byte, reject <-chan yggdrasil.RejectedPacket) {
 | 
				
			||||||
 | 
						m.Adapter.Init(config, log, send, recv, reject)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Name returns the name of the adapter. This is always "dummy" for dummy
 | 
				
			||||||
 | 
					// adapters.
 | 
				
			||||||
 | 
					func (m *DummyAdapter) Name() string {
 | 
				
			||||||
 | 
						return "dummy"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MTU gets the adapter's MTU. This returns your platform's maximum MTU for
 | 
				
			||||||
 | 
					// dummy adapters.
 | 
				
			||||||
 | 
					func (m *DummyAdapter) MTU() int {
 | 
				
			||||||
 | 
						return defaults.GetDefaults().MaximumIfMTU
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsTAP always returns false for dummy adapters.
 | 
				
			||||||
 | 
					func (m *DummyAdapter) IsTAP() bool {
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Recv waits for and returns for a packet from the router.
 | 
				
			||||||
 | 
					func (m *DummyAdapter) Recv() ([]byte, error) {
 | 
				
			||||||
 | 
						packet := <-m.Adapter.Recv
 | 
				
			||||||
 | 
						return packet, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Send a packet to the router.
 | 
				
			||||||
 | 
					func (m *DummyAdapter) Send(buf []byte) error {
 | 
				
			||||||
 | 
						packet := append(util.GetBytes(), buf[:]...)
 | 
				
			||||||
 | 
						m.Adapter.Send <- packet
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Start is not implemented for dummy adapters.
 | 
				
			||||||
 | 
					func (m *DummyAdapter) Start(address.Address, address.Subnet) error {
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Close is not implemented for dummy adapters.
 | 
				
			||||||
 | 
					func (m *DummyAdapter) Close() error {
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
package yggdrasil
 | 
					package mobile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
| 
						 | 
					@ -104,3 +105,4 @@ func (a *awdl) shutdown(identity string) error {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return errors.New("Interface not found or already closed")
 | 
						return errors.New("Interface not found or already closed")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
							
								
								
									
										149
									
								
								src/mobile/mobile.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								src/mobile/mobile.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,149 @@
 | 
				
			||||||
 | 
					package mobile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gologme/log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hjson "github.com/hjson/hjson-go"
 | 
				
			||||||
 | 
						"github.com/mitchellh/mapstructure"
 | 
				
			||||||
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
				
			||||||
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/dummy"
 | 
				
			||||||
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
 | 
				
			||||||
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Yggdrasil mobile package is meant to "plug the gap" for mobile support, as
 | 
				
			||||||
 | 
					// Gomobile will not create headers for Swift/Obj-C etc if they have complex
 | 
				
			||||||
 | 
					// (non-native) types. Therefore for iOS we will expose some nice simple
 | 
				
			||||||
 | 
					// functions. Note that in the case of iOS we handle reading/writing to/from TUN
 | 
				
			||||||
 | 
					// in Swift therefore we use the "dummy" TUN interface instead.
 | 
				
			||||||
 | 
					type Yggdrasil struct {
 | 
				
			||||||
 | 
						core      yggdrasil.Core
 | 
				
			||||||
 | 
						multicast multicast.Multicast
 | 
				
			||||||
 | 
						log       MobileLogger
 | 
				
			||||||
 | 
						dummy.DummyAdapter
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Yggdrasil) addStaticPeers(cfg *config.NodeConfig) {
 | 
				
			||||||
 | 
						if len(cfg.Peers) == 0 && len(cfg.InterfacePeers) == 0 {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							for _, peer := range cfg.Peers {
 | 
				
			||||||
 | 
								m.core.AddPeer(peer, "")
 | 
				
			||||||
 | 
								time.Sleep(time.Second)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for intf, intfpeers := range cfg.InterfacePeers {
 | 
				
			||||||
 | 
								for _, peer := range intfpeers {
 | 
				
			||||||
 | 
									m.core.AddPeer(peer, intf)
 | 
				
			||||||
 | 
									time.Sleep(time.Second)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							time.Sleep(time.Minute)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StartAutoconfigure starts a node with a randomly generated config
 | 
				
			||||||
 | 
					func (m *Yggdrasil) StartAutoconfigure() error {
 | 
				
			||||||
 | 
						logger := log.New(m.log, "", 0)
 | 
				
			||||||
 | 
						logger.EnableLevel("error")
 | 
				
			||||||
 | 
						logger.EnableLevel("warn")
 | 
				
			||||||
 | 
						logger.EnableLevel("info")
 | 
				
			||||||
 | 
						nc := config.GenerateConfig()
 | 
				
			||||||
 | 
						nc.IfName = "dummy"
 | 
				
			||||||
 | 
						nc.AdminListen = "tcp://localhost:9001"
 | 
				
			||||||
 | 
						nc.Peers = []string{}
 | 
				
			||||||
 | 
						if hostname, err := os.Hostname(); err == nil {
 | 
				
			||||||
 | 
							nc.NodeInfo = map[string]interface{}{"name": hostname}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := m.core.SetRouterAdapter(m); err != nil {
 | 
				
			||||||
 | 
							logger.Errorln("An error occured setting router adapter:", err)
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						state, err := m.core.Start(nc, logger)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logger.Errorln("An error occured starting Yggdrasil:", err)
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m.multicast.Init(&m.core, state, logger, nil)
 | 
				
			||||||
 | 
						if err := m.multicast.Start(); err != nil {
 | 
				
			||||||
 | 
							logger.Errorln("An error occurred starting multicast:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						go m.addStaticPeers(nc)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StartJSON starts a node with the given JSON config. You can get JSON config
 | 
				
			||||||
 | 
					// (rather than HJSON) by using the GenerateConfigJSON() function
 | 
				
			||||||
 | 
					func (m *Yggdrasil) StartJSON(configjson []byte) error {
 | 
				
			||||||
 | 
						logger := log.New(m.log, "", 0)
 | 
				
			||||||
 | 
						logger.EnableLevel("error")
 | 
				
			||||||
 | 
						logger.EnableLevel("warn")
 | 
				
			||||||
 | 
						logger.EnableLevel("info")
 | 
				
			||||||
 | 
						nc := config.GenerateConfig()
 | 
				
			||||||
 | 
						var dat map[string]interface{}
 | 
				
			||||||
 | 
						if err := hjson.Unmarshal(configjson, &dat); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := mapstructure.Decode(dat, &nc); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						nc.IfName = "dummy"
 | 
				
			||||||
 | 
						if err := m.core.SetRouterAdapter(m); err != nil {
 | 
				
			||||||
 | 
							logger.Errorln("An error occured setting router adapter:", err)
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						state, err := m.core.Start(nc, logger)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logger.Errorln("An error occured starting Yggdrasil:", err)
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m.multicast.Init(&m.core, state, logger, nil)
 | 
				
			||||||
 | 
						if err := m.multicast.Start(); err != nil {
 | 
				
			||||||
 | 
							logger.Errorln("An error occurred starting multicast:", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						go m.addStaticPeers(nc)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Stop the mobile Yggdrasil instance
 | 
				
			||||||
 | 
					func (m *Yggdrasil) Stop() error {
 | 
				
			||||||
 | 
						m.core.Stop()
 | 
				
			||||||
 | 
						if err := m.Stop(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateConfigJSON generates mobile-friendly configuration in JSON format
 | 
				
			||||||
 | 
					func GenerateConfigJSON() []byte {
 | 
				
			||||||
 | 
						nc := config.GenerateConfig()
 | 
				
			||||||
 | 
						nc.IfName = "dummy"
 | 
				
			||||||
 | 
						if json, err := json.Marshal(nc); err == nil {
 | 
				
			||||||
 | 
							return json
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetAddressString gets the node's IPv6 address
 | 
				
			||||||
 | 
					func (m *Yggdrasil) GetAddressString() string {
 | 
				
			||||||
 | 
						return m.core.Address().String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetSubnetString gets the node's IPv6 subnet in CIDR notation
 | 
				
			||||||
 | 
					func (m *Yggdrasil) GetSubnetString() string {
 | 
				
			||||||
 | 
						return m.core.Subnet().String()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetBoxPubKeyString gets the node's public encryption key
 | 
				
			||||||
 | 
					func (m *Yggdrasil) GetBoxPubKeyString() string {
 | 
				
			||||||
 | 
						return m.core.BoxPubKey()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetSigPubKeyString gets the node's public signing key
 | 
				
			||||||
 | 
					func (m *Yggdrasil) GetSigPubKeyString() string {
 | 
				
			||||||
 | 
						return m.core.SigPubKey()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
// +build android
 | 
					// +build android
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package yggdrasil
 | 
					package mobile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "log"
 | 
					import "log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
// +build mobile,darwin
 | 
					// +build darwin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package yggdrasil
 | 
					package mobile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
#cgo CFLAGS: -x objective-c
 | 
					#cgo CFLAGS: -x objective-c
 | 
				
			||||||
| 
						 | 
					@ -13,10 +13,7 @@ void Log(const char *text) {
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
import "C"
 | 
					import "C"
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"unsafe"
 | 
						"unsafe"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type MobileLogger struct {
 | 
					type MobileLogger struct {
 | 
				
			||||||
| 
						 | 
					@ -29,6 +26,7 @@ func (nsl MobileLogger) Write(p []byte) (n int, err error) {
 | 
				
			||||||
	return len(p), nil
 | 
						return len(p), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
func (c *Core) AWDLCreateInterface(name, local, remote string, incoming bool) error {
 | 
					func (c *Core) AWDLCreateInterface(name, local, remote string, incoming bool) error {
 | 
				
			||||||
	if intf, err := c.link.awdl.create(name, local, remote, incoming); err != nil || intf == nil {
 | 
						if intf, err := c.link.awdl.create(name, local, remote, incoming); err != nil || intf == nil {
 | 
				
			||||||
		c.log.Println("c.link.awdl.create:", err)
 | 
							c.log.Println("c.link.awdl.create:", err)
 | 
				
			||||||
| 
						 | 
					@ -60,3 +58,4 @@ func (c *Core) AWDLSendPacket(identity string, buf []byte) error {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return errors.New("AWDLSendPacket identity not known: " + identity)
 | 
						return errors.New("AWDLSendPacket identity not known: " + identity)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package yggdrasil
 | 
					package multicast
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
| 
						 | 
					@ -7,25 +7,37 @@ import (
 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gologme/log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
				
			||||||
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
 | 
				
			||||||
	"golang.org/x/net/ipv6"
 | 
						"golang.org/x/net/ipv6"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type multicast struct {
 | 
					// Multicast represents the multicast advertisement and discovery mechanism used
 | 
				
			||||||
	core        *Core
 | 
					// by Yggdrasil to find peers on the same subnet. When a beacon is received on a
 | 
				
			||||||
 | 
					// configured multicast interface, Yggdrasil will attempt to peer with that node
 | 
				
			||||||
 | 
					// automatically.
 | 
				
			||||||
 | 
					type Multicast struct {
 | 
				
			||||||
 | 
						core        *yggdrasil.Core
 | 
				
			||||||
 | 
						config      *config.NodeState
 | 
				
			||||||
 | 
						log         *log.Logger
 | 
				
			||||||
	reconfigure chan chan error
 | 
						reconfigure chan chan error
 | 
				
			||||||
	sock        *ipv6.PacketConn
 | 
						sock        *ipv6.PacketConn
 | 
				
			||||||
	groupAddr   string
 | 
						groupAddr   string
 | 
				
			||||||
	listeners   map[string]*tcpListener
 | 
						listeners   map[string]*yggdrasil.TcpListener
 | 
				
			||||||
	listenPort  uint16
 | 
						listenPort  uint16
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) init(core *Core) {
 | 
					// Init prepares the multicast interface for use.
 | 
				
			||||||
 | 
					func (m *Multicast) Init(core *yggdrasil.Core, state *config.NodeState, log *log.Logger, options interface{}) error {
 | 
				
			||||||
	m.core = core
 | 
						m.core = core
 | 
				
			||||||
 | 
						m.config = state
 | 
				
			||||||
 | 
						m.log = log
 | 
				
			||||||
	m.reconfigure = make(chan chan error, 1)
 | 
						m.reconfigure = make(chan chan error, 1)
 | 
				
			||||||
	m.listeners = make(map[string]*tcpListener)
 | 
						m.listeners = make(map[string]*yggdrasil.TcpListener)
 | 
				
			||||||
	m.core.configMutex.RLock()
 | 
						current, _ := m.config.Get()
 | 
				
			||||||
	m.listenPort = m.core.config.LinkLocalTCPPort
 | 
						m.listenPort = current.LinkLocalTCPPort
 | 
				
			||||||
	m.core.configMutex.RUnlock()
 | 
					 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			e := <-m.reconfigure
 | 
								e := <-m.reconfigure
 | 
				
			||||||
| 
						 | 
					@ -35,15 +47,19 @@ func (m *multicast) init(core *Core) {
 | 
				
			||||||
	m.groupAddr = "[ff02::114]:9001"
 | 
						m.groupAddr = "[ff02::114]:9001"
 | 
				
			||||||
	// Check if we've been given any expressions
 | 
						// Check if we've been given any expressions
 | 
				
			||||||
	if count := len(m.interfaces()); count != 0 {
 | 
						if count := len(m.interfaces()); count != 0 {
 | 
				
			||||||
		m.core.log.Infoln("Found", count, "multicast interface(s)")
 | 
							m.log.Infoln("Found", count, "multicast interface(s)")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) start() error {
 | 
					// Start starts the multicast interface. This launches goroutines which will
 | 
				
			||||||
 | 
					// listen for multicast beacons from other hosts and will advertise multicast
 | 
				
			||||||
 | 
					// beacons out to the network.
 | 
				
			||||||
 | 
					func (m *Multicast) Start() error {
 | 
				
			||||||
	if len(m.interfaces()) == 0 {
 | 
						if len(m.interfaces()) == 0 {
 | 
				
			||||||
		m.core.log.Infoln("Multicast discovery is disabled")
 | 
							m.log.Infoln("Multicast discovery is disabled")
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		m.core.log.Infoln("Multicast discovery is enabled")
 | 
							m.log.Infoln("Multicast discovery is enabled")
 | 
				
			||||||
		addr, err := net.ResolveUDPAddr("udp", m.groupAddr)
 | 
							addr, err := net.ResolveUDPAddr("udp", m.groupAddr)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
| 
						 | 
					@ -68,11 +84,15 @@ func (m *multicast) start() error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) interfaces() map[string]net.Interface {
 | 
					// Stop is not implemented for multicast yet.
 | 
				
			||||||
 | 
					func (m *Multicast) Stop() error {
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Multicast) interfaces() map[string]net.Interface {
 | 
				
			||||||
	// Get interface expressions from config
 | 
						// Get interface expressions from config
 | 
				
			||||||
	m.core.configMutex.RLock()
 | 
						current, _ := m.config.Get()
 | 
				
			||||||
	exprs := m.core.config.MulticastInterfaces
 | 
						exprs := current.MulticastInterfaces
 | 
				
			||||||
	m.core.configMutex.RUnlock()
 | 
					 | 
				
			||||||
	// Ask the system for network interfaces
 | 
						// Ask the system for network interfaces
 | 
				
			||||||
	interfaces := make(map[string]net.Interface)
 | 
						interfaces := make(map[string]net.Interface)
 | 
				
			||||||
	allifaces, err := net.Interfaces()
 | 
						allifaces, err := net.Interfaces()
 | 
				
			||||||
| 
						 | 
					@ -108,7 +128,7 @@ func (m *multicast) interfaces() map[string]net.Interface {
 | 
				
			||||||
	return interfaces
 | 
						return interfaces
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) announce() {
 | 
					func (m *Multicast) announce() {
 | 
				
			||||||
	groupAddr, err := net.ResolveUDPAddr("udp6", m.groupAddr)
 | 
						groupAddr, err := net.ResolveUDPAddr("udp6", m.groupAddr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
| 
						 | 
					@ -124,9 +144,9 @@ func (m *multicast) announce() {
 | 
				
			||||||
		for name, listener := range m.listeners {
 | 
							for name, listener := range m.listeners {
 | 
				
			||||||
			// Prepare our stop function!
 | 
								// Prepare our stop function!
 | 
				
			||||||
			stop := func() {
 | 
								stop := func() {
 | 
				
			||||||
				listener.stop <- true
 | 
									listener.Stop <- true
 | 
				
			||||||
				delete(m.listeners, name)
 | 
									delete(m.listeners, name)
 | 
				
			||||||
				m.core.log.Debugln("No longer multicasting on", name)
 | 
									m.log.Debugln("No longer multicasting on", name)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// If the interface is no longer visible on the system then stop the
 | 
								// If the interface is no longer visible on the system then stop the
 | 
				
			||||||
			// listener, as another one will be started further down
 | 
								// listener, as another one will be started further down
 | 
				
			||||||
| 
						 | 
					@ -137,7 +157,7 @@ func (m *multicast) announce() {
 | 
				
			||||||
			// It's possible that the link-local listener address has changed so if
 | 
								// It's possible that the link-local listener address has changed so if
 | 
				
			||||||
			// that is the case then we should clean up the interface listener
 | 
								// that is the case then we should clean up the interface listener
 | 
				
			||||||
			found := false
 | 
								found := false
 | 
				
			||||||
			listenaddr, err := net.ResolveTCPAddr("tcp6", listener.listener.Addr().String())
 | 
								listenaddr, err := net.ResolveTCPAddr("tcp6", listener.Listener.Addr().String())
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				stop()
 | 
									stop()
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
| 
						 | 
					@ -186,17 +206,17 @@ func (m *multicast) announce() {
 | 
				
			||||||
				// Join the multicast group
 | 
									// Join the multicast group
 | 
				
			||||||
				m.sock.JoinGroup(&iface, groupAddr)
 | 
									m.sock.JoinGroup(&iface, groupAddr)
 | 
				
			||||||
				// Try and see if we already have a TCP listener for this interface
 | 
									// Try and see if we already have a TCP listener for this interface
 | 
				
			||||||
				var listener *tcpListener
 | 
									var listener *yggdrasil.TcpListener
 | 
				
			||||||
				if l, ok := m.listeners[iface.Name]; !ok || l.listener == nil {
 | 
									if l, ok := m.listeners[iface.Name]; !ok || l.Listener == nil {
 | 
				
			||||||
					// No listener was found - let's create one
 | 
										// No listener was found - let's create one
 | 
				
			||||||
					listenaddr := fmt.Sprintf("[%s%%%s]:%d", addrIP, iface.Name, m.listenPort)
 | 
										listenaddr := fmt.Sprintf("[%s%%%s]:%d", addrIP, iface.Name, m.listenPort)
 | 
				
			||||||
					if li, err := m.core.link.tcp.listen(listenaddr); err == nil {
 | 
										if li, err := m.core.ListenTCP(listenaddr); err == nil {
 | 
				
			||||||
						m.core.log.Debugln("Started multicasting on", iface.Name)
 | 
											m.log.Debugln("Started multicasting on", iface.Name)
 | 
				
			||||||
						// Store the listener so that we can stop it later if needed
 | 
											// Store the listener so that we can stop it later if needed
 | 
				
			||||||
						m.listeners[iface.Name] = li
 | 
											m.listeners[iface.Name] = li
 | 
				
			||||||
						listener = li
 | 
											listener = li
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						m.core.log.Warnln("Not multicasting on", iface.Name, "due to error:", err)
 | 
											m.log.Warnln("Not multicasting on", iface.Name, "due to error:", err)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					// An existing listener was found
 | 
										// An existing listener was found
 | 
				
			||||||
| 
						 | 
					@ -207,7 +227,7 @@ func (m *multicast) announce() {
 | 
				
			||||||
					continue
 | 
										continue
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				// Get the listener details and construct the multicast beacon
 | 
									// Get the listener details and construct the multicast beacon
 | 
				
			||||||
				lladdr := listener.listener.Addr().String()
 | 
									lladdr := listener.Listener.Addr().String()
 | 
				
			||||||
				if a, err := net.ResolveTCPAddr("tcp6", lladdr); err == nil {
 | 
									if a, err := net.ResolveTCPAddr("tcp6", lladdr); err == nil {
 | 
				
			||||||
					a.Zone = ""
 | 
										a.Zone = ""
 | 
				
			||||||
					destAddr.Zone = iface.Name
 | 
										destAddr.Zone = iface.Name
 | 
				
			||||||
| 
						 | 
					@ -221,7 +241,7 @@ func (m *multicast) announce() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) listen() {
 | 
					func (m *Multicast) listen() {
 | 
				
			||||||
	groupAddr, err := net.ResolveUDPAddr("udp6", m.groupAddr)
 | 
						groupAddr, err := net.ResolveUDPAddr("udp6", m.groupAddr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
| 
						 | 
					@ -253,8 +273,8 @@ func (m *multicast) listen() {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		addr.Zone = ""
 | 
							addr.Zone = ""
 | 
				
			||||||
		if err := m.core.link.call("tcp://"+addr.String(), from.Zone); err != nil {
 | 
							if err := m.core.CallPeer("tcp://"+addr.String(), from.Zone); err != nil {
 | 
				
			||||||
			m.core.log.Debugln("Call from multicast failed:", err)
 | 
								m.log.Debugln("Call from multicast failed:", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
// +build darwin
 | 
					// +build darwin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package yggdrasil
 | 
					package multicast
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
#cgo CFLAGS: -x objective-c
 | 
					#cgo CFLAGS: -x objective-c
 | 
				
			||||||
| 
						 | 
					@ -31,11 +31,11 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var awdlGoroutineStarted bool
 | 
					var awdlGoroutineStarted bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) multicastStarted() {
 | 
					func (m *Multicast) multicastStarted() {
 | 
				
			||||||
	if awdlGoroutineStarted {
 | 
						if awdlGoroutineStarted {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	m.core.log.Infoln("Multicast discovery will wake up AWDL if required")
 | 
						m.log.Infoln("Multicast discovery will wake up AWDL if required")
 | 
				
			||||||
	awdlGoroutineStarted = true
 | 
						awdlGoroutineStarted = true
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		C.StopAWDLBrowsing()
 | 
							C.StopAWDLBrowsing()
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,7 @@ func (m *multicast) multicastStarted() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) multicastReuse(network string, address string, c syscall.RawConn) error {
 | 
					func (m *Multicast) multicastReuse(network string, address string, c syscall.RawConn) error {
 | 
				
			||||||
	var control error
 | 
						var control error
 | 
				
			||||||
	var reuseport error
 | 
						var reuseport error
 | 
				
			||||||
	var recvanyif error
 | 
						var recvanyif error
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,13 @@
 | 
				
			||||||
// +build !linux,!darwin,!netbsd,!freebsd,!openbsd,!dragonflybsd,!windows
 | 
					// +build !linux,!darwin,!netbsd,!freebsd,!openbsd,!dragonflybsd,!windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package yggdrasil
 | 
					package multicast
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "syscall"
 | 
					import "syscall"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) multicastStarted() {
 | 
					func (m *Multicast) multicastStarted() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) multicastReuse(network string, address string, c syscall.RawConn) error {
 | 
					func (m *Multicast) multicastReuse(network string, address string, c syscall.RawConn) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,15 @@
 | 
				
			||||||
// +build linux netbsd freebsd openbsd dragonflybsd
 | 
					// +build linux netbsd freebsd openbsd dragonflybsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package yggdrasil
 | 
					package multicast
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "syscall"
 | 
					import "syscall"
 | 
				
			||||||
import "golang.org/x/sys/unix"
 | 
					import "golang.org/x/sys/unix"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) multicastStarted() {
 | 
					func (m *Multicast) multicastStarted() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) multicastReuse(network string, address string, c syscall.RawConn) error {
 | 
					func (m *Multicast) multicastReuse(network string, address string, c syscall.RawConn) error {
 | 
				
			||||||
	var control error
 | 
						var control error
 | 
				
			||||||
	var reuseport error
 | 
						var reuseport error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,15 @@
 | 
				
			||||||
// +build windows
 | 
					// +build windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package yggdrasil
 | 
					package multicast
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "syscall"
 | 
					import "syscall"
 | 
				
			||||||
import "golang.org/x/sys/windows"
 | 
					import "golang.org/x/sys/windows"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) multicastStarted() {
 | 
					func (m *Multicast) multicastStarted() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *multicast) multicastReuse(network string, address string, c syscall.RawConn) error {
 | 
					func (m *Multicast) multicastReuse(network string, address string, c syscall.RawConn) error {
 | 
				
			||||||
	var control error
 | 
						var control error
 | 
				
			||||||
	var reuseaddr error
 | 
						var reuseaddr error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package yggdrasil
 | 
					package tuntap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The ICMPv6 module implements functions to easily create ICMPv6
 | 
					// The ICMPv6 module implements functions to easily create ICMPv6
 | 
				
			||||||
// packets. These functions, when mixed with the built-in Go IPv6
 | 
					// packets. These functions, when mixed with the built-in Go IPv6
 | 
				
			||||||
| 
						 | 
					@ -25,8 +25,8 @@ type macAddress [6]byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const len_ETHER = 14
 | 
					const len_ETHER = 14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type icmpv6 struct {
 | 
					type ICMPv6 struct {
 | 
				
			||||||
	tun      *tunAdapter
 | 
						tun      *TunAdapter
 | 
				
			||||||
	mylladdr net.IP
 | 
						mylladdr net.IP
 | 
				
			||||||
	mymac    macAddress
 | 
						mymac    macAddress
 | 
				
			||||||
	peermacs map[address.Address]neighbor
 | 
						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
 | 
					// Initialises the ICMPv6 module by assigning our link-local IPv6 address and
 | 
				
			||||||
// our MAC address. ICMPv6 messages will always appear to originate from these
 | 
					// our MAC address. ICMPv6 messages will always appear to originate from these
 | 
				
			||||||
// addresses.
 | 
					// addresses.
 | 
				
			||||||
func (i *icmpv6) init(t *tunAdapter) {
 | 
					func (i *ICMPv6) Init(t *TunAdapter) {
 | 
				
			||||||
	i.tun = t
 | 
						i.tun = t
 | 
				
			||||||
	i.peermacs = make(map[address.Address]neighbor)
 | 
						i.peermacs = make(map[address.Address]neighbor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,23 +69,23 @@ func (i *icmpv6) init(t *tunAdapter) {
 | 
				
			||||||
	i.mylladdr = net.IP{
 | 
						i.mylladdr = net.IP{
 | 
				
			||||||
		0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
							0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
				
			||||||
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFE}
 | 
							0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFE}
 | 
				
			||||||
	copy(i.mymac[:], i.tun.core.router.addr[:])
 | 
						copy(i.mymac[:], i.tun.addr[:])
 | 
				
			||||||
	copy(i.mylladdr[9:], i.tun.core.router.addr[1:])
 | 
						copy(i.mylladdr[9:], i.tun.addr[1:])
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Parses an incoming ICMPv6 packet. The packet provided may be either an
 | 
					// 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
 | 
					// 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
 | 
					// determined by whether the TUN/TAP adapter is running in TUN (layer 3) or
 | 
				
			||||||
// TAP (layer 2) mode.
 | 
					// TAP (layer 2) mode.
 | 
				
			||||||
func (i *icmpv6) parse_packet(datain []byte) {
 | 
					func (i *ICMPv6) ParsePacket(datain []byte) {
 | 
				
			||||||
	var response []byte
 | 
						var response []byte
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Parse the frame/packet
 | 
						// Parse the frame/packet
 | 
				
			||||||
	if i.tun.iface.IsTAP() {
 | 
						if i.tun.IsTAP() {
 | 
				
			||||||
		response, err = i.parse_packet_tap(datain)
 | 
							response, err = i.UnmarshalPacketL2(datain)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		response, err = i.parse_packet_tun(datain, nil)
 | 
							response, err = i.UnmarshalPacket(datain, nil)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -97,18 +97,18 @@ func (i *icmpv6) parse_packet(datain []byte) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Unwraps the ethernet headers of an incoming ICMPv6 packet and hands off
 | 
					// 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
 | 
					// A response buffer is also created for the response message, also complete
 | 
				
			||||||
// with ethernet headers.
 | 
					// 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
 | 
						// Ignore non-IPv6 frames
 | 
				
			||||||
	if binary.BigEndian.Uint16(datain[12:14]) != uint16(0x86DD) {
 | 
						if binary.BigEndian.Uint16(datain[12:14]) != uint16(0x86DD) {
 | 
				
			||||||
		return nil, nil
 | 
							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]
 | 
						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 {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							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
 | 
					// 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
 | 
					// ICMPv6 message match a known expected type. The relevant handler function
 | 
				
			||||||
// is then called and a response packet may be returned.
 | 
					// 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
 | 
						// Parse the IPv6 packet headers
 | 
				
			||||||
	ipv6Header, err := ipv6.ParseHeader(datain[:ipv6.HeaderLen])
 | 
						ipv6Header, err := ipv6.ParseHeader(datain[:ipv6.HeaderLen])
 | 
				
			||||||
	if err != nil {
 | 
						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
 | 
						// Check for a supported message type
 | 
				
			||||||
	switch icmpv6Header.Type {
 | 
						switch icmpv6Header.Type {
 | 
				
			||||||
	case ipv6.ICMPTypeNeighborSolicitation:
 | 
						case ipv6.ICMPTypeNeighborSolicitation:
 | 
				
			||||||
		if !i.tun.iface.IsTAP() {
 | 
							if !i.tun.IsTAP() {
 | 
				
			||||||
			return nil, errors.New("Ignoring Neighbor Solicitation in TUN mode")
 | 
								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 {
 | 
							if err == nil {
 | 
				
			||||||
			// Create our ICMPv6 response
 | 
								// Create our ICMPv6 response
 | 
				
			||||||
			responsePacket, err := i.create_icmpv6_tun(
 | 
								responsePacket, err := CreateICMPv6(
 | 
				
			||||||
				ipv6Header.Src, i.mylladdr,
 | 
									ipv6Header.Src, i.mylladdr,
 | 
				
			||||||
				ipv6.ICMPTypeNeighborAdvertisement, 0,
 | 
									ipv6.ICMPTypeNeighborAdvertisement, 0,
 | 
				
			||||||
				&icmp.DefaultMessageBody{Data: response})
 | 
									&icmp.DefaultMessageBody{Data: response})
 | 
				
			||||||
| 
						 | 
					@ -176,7 +176,7 @@ func (i *icmpv6) parse_packet_tun(datain []byte, datamac *[]byte) ([]byte, error
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case ipv6.ICMPTypeNeighborAdvertisement:
 | 
						case ipv6.ICMPTypeNeighborAdvertisement:
 | 
				
			||||||
		if !i.tun.iface.IsTAP() {
 | 
							if !i.tun.IsTAP() {
 | 
				
			||||||
			return nil, errors.New("Ignoring Neighbor Advertisement in TUN mode")
 | 
								return nil, errors.New("Ignoring Neighbor Advertisement in TUN mode")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if datamac != nil {
 | 
							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
 | 
					// Creates an ICMPv6 packet based on the given icmp.MessageBody and other
 | 
				
			||||||
// parameters, complete with ethernet and IP headers, which can be written
 | 
					// parameters, complete with ethernet and IP headers, which can be written
 | 
				
			||||||
// directly to a TAP adapter.
 | 
					// 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) {
 | 
					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 create_icmpv6_tun
 | 
						// Pass through to CreateICMPv6
 | 
				
			||||||
	ipv6packet, err := i.create_icmpv6_tun(dst, src, mtype, mcode, mbody)
 | 
						ipv6packet, err := CreateICMPv6(dst, src, mtype, mcode, mbody)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							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
 | 
					// Creates an ICMPv6 packet based on the given icmp.MessageBody and other
 | 
				
			||||||
// parameters, complete with IP headers only, which can be written directly to
 | 
					// 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.
 | 
					// 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
 | 
						// Create the ICMPv6 message
 | 
				
			||||||
	icmpMessage := icmp.Message{
 | 
						icmpMessage := icmp.Message{
 | 
				
			||||||
		Type: mtype,
 | 
							Type: mtype,
 | 
				
			||||||
| 
						 | 
					@ -265,7 +265,7 @@ func (i *icmpv6) create_icmpv6_tun(dst net.IP, src net.IP, mtype ipv6.ICMPType,
 | 
				
			||||||
	return responsePacket, nil
 | 
						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
 | 
						// Create the ND payload
 | 
				
			||||||
	var payload [28]byte
 | 
						var payload [28]byte
 | 
				
			||||||
	copy(payload[:4], []byte{0x00, 0x00, 0x00, 0x00})
 | 
						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])
 | 
						copy(dstmac[2:6], dstaddr[12:16])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Create the ND request
 | 
						// Create the ND request
 | 
				
			||||||
	requestPacket, err := i.create_icmpv6_tap(
 | 
						requestPacket, err := i.CreateICMPv6L2(
 | 
				
			||||||
		dstmac, dstaddr[:], i.mylladdr,
 | 
							dstmac, dstaddr[:], i.mylladdr,
 | 
				
			||||||
		ipv6.ICMPTypeNeighborSolicitation, 0,
 | 
							ipv6.ICMPTypeNeighborSolicitation, 0,
 | 
				
			||||||
		&icmp.DefaultMessageBody{Data: payload[:]})
 | 
							&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
 | 
					// 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
 | 
					// the fd00::/8 range, so that the operating system knows to route that traffic
 | 
				
			||||||
// to the Yggdrasil TAP adapter.
 | 
					// 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
 | 
						// Ignore NDP requests for anything outside of fd00::/8
 | 
				
			||||||
	var source address.Address
 | 
						var source address.Address
 | 
				
			||||||
	copy(source[:], in[8:])
 | 
						copy(source[:], in[8:])
 | 
				
			||||||
							
								
								
									
										361
									
								
								src/tuntap/tun.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										361
									
								
								src/tuntap/tun.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,361 @@
 | 
				
			||||||
 | 
					package tuntap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This manages the tun driver to send/recv packets to/from applications
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"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/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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TunAdapter represents a running TUN/TAP interface and extends the
 | 
				
			||||||
 | 
					// yggdrasil.Adapter type. In order to use the TUN/TAP adapter with Yggdrasil,
 | 
				
			||||||
 | 
					// you should pass this object to the yggdrasil.SetRouterAdapter() function
 | 
				
			||||||
 | 
					// before calling yggdrasil.Start().
 | 
				
			||||||
 | 
					type TunAdapter struct {
 | 
				
			||||||
 | 
						yggdrasil.Adapter
 | 
				
			||||||
 | 
						addr   address.Address
 | 
				
			||||||
 | 
						subnet address.Subnet
 | 
				
			||||||
 | 
						icmpv6 ICMPv6
 | 
				
			||||||
 | 
						mtu    int
 | 
				
			||||||
 | 
						iface  *water.Interface
 | 
				
			||||||
 | 
						mutex  sync.RWMutex // Protects the below
 | 
				
			||||||
 | 
						isOpen bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Gets the maximum supported MTU for the platform based on the defaults in
 | 
				
			||||||
 | 
					// defaults.GetDefaults().
 | 
				
			||||||
 | 
					func getSupportedMTU(mtu int) int {
 | 
				
			||||||
 | 
						if mtu > defaults.GetDefaults().MaximumIfMTU {
 | 
				
			||||||
 | 
							return defaults.GetDefaults().MaximumIfMTU
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return mtu
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Name returns the name of the adapter, e.g. "tun0". On Windows, this may
 | 
				
			||||||
 | 
					// return a canonical adapter name instead.
 | 
				
			||||||
 | 
					func (tun *TunAdapter) Name() string {
 | 
				
			||||||
 | 
						return tun.iface.Name()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MTU gets the adapter's MTU. This can range between 1280 and 65535, although
 | 
				
			||||||
 | 
					// the maximum value is determined by your platform. The returned value will
 | 
				
			||||||
 | 
					// never exceed that of MaximumMTU().
 | 
				
			||||||
 | 
					func (tun *TunAdapter) MTU() int {
 | 
				
			||||||
 | 
						return getSupportedMTU(tun.mtu)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsTAP returns true if the adapter is a TAP adapter (Layer 2) or false if it
 | 
				
			||||||
 | 
					// is a TUN adapter (Layer 3).
 | 
				
			||||||
 | 
					func (tun *TunAdapter) IsTAP() bool {
 | 
				
			||||||
 | 
						return tun.iface.IsTAP()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DefaultName gets the default TUN/TAP interface name for your platform.
 | 
				
			||||||
 | 
					func DefaultName() string {
 | 
				
			||||||
 | 
						return defaults.GetDefaults().DefaultIfName
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DefaultMTU gets the default TUN/TAP interface MTU for your platform. This can
 | 
				
			||||||
 | 
					// be as high as MaximumMTU(), depending on platform, but is never lower than 1280.
 | 
				
			||||||
 | 
					func DefaultMTU() int {
 | 
				
			||||||
 | 
						return defaults.GetDefaults().DefaultIfMTU
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DefaultIsTAP returns true if the default adapter mode for the current
 | 
				
			||||||
 | 
					// platform is TAP (Layer 2) and returns false for TUN (Layer 3).
 | 
				
			||||||
 | 
					func DefaultIsTAP() bool {
 | 
				
			||||||
 | 
						return defaults.GetDefaults().DefaultIfTAPMode
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MaximumMTU returns the maximum supported TUN/TAP interface MTU for your
 | 
				
			||||||
 | 
					// platform. This can be as high as 65535, depending on platform, but is never
 | 
				
			||||||
 | 
					// lower than 1280.
 | 
				
			||||||
 | 
					func MaximumMTU() int {
 | 
				
			||||||
 | 
						return defaults.GetDefaults().MaximumIfMTU
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Init initialises the TUN/TAP adapter.
 | 
				
			||||||
 | 
					func (tun *TunAdapter) Init(config *config.NodeState, log *log.Logger, send chan<- []byte, recv <-chan []byte, reject <-chan yggdrasil.RejectedPacket) {
 | 
				
			||||||
 | 
						tun.Adapter.Init(config, log, send, recv, reject)
 | 
				
			||||||
 | 
						tun.icmpv6.Init(tun)
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								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.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
 | 
				
			||||||
 | 
					// read/write goroutines to handle packets on that interface.
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if ifname == "none" || ifname == "dummy" {
 | 
				
			||||||
 | 
							tun.Log.Debugln("Not starting TUN/TAP as ifname is none or dummy")
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tun.mutex.Lock()
 | 
				
			||||||
 | 
						tun.isOpen = true
 | 
				
			||||||
 | 
						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 {
 | 
				
			||||||
 | 
							go func() {
 | 
				
			||||||
 | 
								for {
 | 
				
			||||||
 | 
									if _, ok := tun.icmpv6.peermacs[tun.addr]; ok {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									request, err := tun.icmpv6.CreateNDPL2(tun.addr)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										panic(err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if _, err := tun.iface.Write(request); err != nil {
 | 
				
			||||||
 | 
										panic(err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									time.Sleep(time.Second)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 {
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case reject := <-tun.Reject:
 | 
				
			||||||
 | 
								switch reject.Reason {
 | 
				
			||||||
 | 
								case yggdrasil.PacketTooBig:
 | 
				
			||||||
 | 
									if mtu, ok := reject.Detail.(int); ok {
 | 
				
			||||||
 | 
										// Create the Packet Too Big response
 | 
				
			||||||
 | 
										ptb := &icmp.PacketTooBig{
 | 
				
			||||||
 | 
											MTU:  int(mtu),
 | 
				
			||||||
 | 
											Data: reject.Packet,
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// Create the ICMPv6 response from it
 | 
				
			||||||
 | 
										icmpv6Buf, err := CreateICMPv6(
 | 
				
			||||||
 | 
											reject.Packet[8:24], reject.Packet[24:40],
 | 
				
			||||||
 | 
											ipv6.ICMPTypePacketTooBig, 0, ptb)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// Send the ICMPv6 response back to the TUN/TAP adapter
 | 
				
			||||||
 | 
										if err == nil {
 | 
				
			||||||
 | 
											tun.iface.Write(icmpv6Buf)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									fallthrough
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							case data := <-tun.Recv:
 | 
				
			||||||
 | 
								if tun.iface == nil {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if tun.iface.IsTAP() {
 | 
				
			||||||
 | 
									var destAddr address.Address
 | 
				
			||||||
 | 
									if data[0]&0xf0 == 0x60 {
 | 
				
			||||||
 | 
										if len(data) < 40 {
 | 
				
			||||||
 | 
											//panic("Tried to send a packet shorter than an IPv6 header...")
 | 
				
			||||||
 | 
											util.PutBytes(data)
 | 
				
			||||||
 | 
											continue
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										copy(destAddr[:16], data[24:])
 | 
				
			||||||
 | 
									} else if data[0]&0xf0 == 0x40 {
 | 
				
			||||||
 | 
										if len(data) < 20 {
 | 
				
			||||||
 | 
											//panic("Tried to send a packet shorter than an IPv4 header...")
 | 
				
			||||||
 | 
											util.PutBytes(data)
 | 
				
			||||||
 | 
											continue
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										copy(destAddr[:4], data[16:])
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										return errors.New("Invalid address family")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									sendndp := func(destAddr address.Address) {
 | 
				
			||||||
 | 
										neigh, known := tun.icmpv6.peermacs[destAddr]
 | 
				
			||||||
 | 
										known = known && (time.Since(neigh.lastsolicitation).Seconds() < 30)
 | 
				
			||||||
 | 
										if !known {
 | 
				
			||||||
 | 
											request, err := tun.icmpv6.CreateNDPL2(destAddr)
 | 
				
			||||||
 | 
											if err != nil {
 | 
				
			||||||
 | 
												panic(err)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											if _, err := tun.iface.Write(request); err != nil {
 | 
				
			||||||
 | 
												panic(err)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											tun.icmpv6.peermacs[destAddr] = neighbor{
 | 
				
			||||||
 | 
												lastsolicitation: time.Now(),
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									var peermac macAddress
 | 
				
			||||||
 | 
									var peerknown bool
 | 
				
			||||||
 | 
									if data[0]&0xf0 == 0x40 {
 | 
				
			||||||
 | 
										destAddr = tun.addr
 | 
				
			||||||
 | 
									} else if data[0]&0xf0 == 0x60 {
 | 
				
			||||||
 | 
										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.addr]; ok && neighbor.learned {
 | 
				
			||||||
 | 
										peermac = neighbor.mac
 | 
				
			||||||
 | 
										peerknown = true
 | 
				
			||||||
 | 
										sendndp(destAddr)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										sendndp(tun.addr)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if peerknown {
 | 
				
			||||||
 | 
										var proto ethernet.Ethertype
 | 
				
			||||||
 | 
										switch {
 | 
				
			||||||
 | 
										case data[0]&0xf0 == 0x60:
 | 
				
			||||||
 | 
											proto = ethernet.IPv6
 | 
				
			||||||
 | 
										case data[0]&0xf0 == 0x40:
 | 
				
			||||||
 | 
											proto = ethernet.IPv4
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										var frame ethernet.Frame
 | 
				
			||||||
 | 
										frame.Prepare(
 | 
				
			||||||
 | 
											peermac[:6],          // Destination MAC address
 | 
				
			||||||
 | 
											tun.icmpv6.mymac[:6], // Source MAC address
 | 
				
			||||||
 | 
											ethernet.NotTagged,   // VLAN tagging
 | 
				
			||||||
 | 
											proto,                // Ethertype
 | 
				
			||||||
 | 
											len(data))            // Payload length
 | 
				
			||||||
 | 
										copy(frame[tun_ETHER_HEADER_LENGTH:], data[:])
 | 
				
			||||||
 | 
										if _, err := tun.iface.Write(frame); err != nil {
 | 
				
			||||||
 | 
											tun.mutex.RLock()
 | 
				
			||||||
 | 
											open := tun.isOpen
 | 
				
			||||||
 | 
											tun.mutex.RUnlock()
 | 
				
			||||||
 | 
											if !open {
 | 
				
			||||||
 | 
												return nil
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												panic(err)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									if _, err := tun.iface.Write(data); err != nil {
 | 
				
			||||||
 | 
										tun.mutex.RLock()
 | 
				
			||||||
 | 
										open := tun.isOpen
 | 
				
			||||||
 | 
										tun.mutex.RUnlock()
 | 
				
			||||||
 | 
										if !open {
 | 
				
			||||||
 | 
											return nil
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											panic(err)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								util.PutBytes(data)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Reads any packets that are waiting on the TUN/TAP adapter. If the adapter
 | 
				
			||||||
 | 
					// 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 {
 | 
				
			||||||
 | 
						mtu := tun.mtu
 | 
				
			||||||
 | 
						if tun.iface.IsTAP() {
 | 
				
			||||||
 | 
							mtu += tun_ETHER_HEADER_LENGTH
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						buf := make([]byte, mtu)
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							n, err := tun.iface.Read(buf)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								tun.mutex.RLock()
 | 
				
			||||||
 | 
								open := tun.isOpen
 | 
				
			||||||
 | 
								tun.mutex.RUnlock()
 | 
				
			||||||
 | 
								if !open {
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							o := 0
 | 
				
			||||||
 | 
							if tun.iface.IsTAP() {
 | 
				
			||||||
 | 
								o = tun_ETHER_HEADER_LENGTH
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							switch {
 | 
				
			||||||
 | 
							case buf[o]&0xf0 == 0x60 && n == 256*int(buf[o+4])+int(buf[o+5])+tun_IPv6_HEADER_LENGTH+o:
 | 
				
			||||||
 | 
							case buf[o]&0xf0 == 0x40 && n == 256*int(buf[o+2])+int(buf[o+3])+o:
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if buf[o+6] == 58 {
 | 
				
			||||||
 | 
								if tun.iface.IsTAP() {
 | 
				
			||||||
 | 
									// Found an ICMPv6 packet
 | 
				
			||||||
 | 
									b := make([]byte, n)
 | 
				
			||||||
 | 
									copy(b, buf)
 | 
				
			||||||
 | 
									go tun.icmpv6.ParsePacket(b)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							packet := append(util.GetBytes(), buf[o:n]...)
 | 
				
			||||||
 | 
							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 {
 | 
				
			||||||
 | 
						tun.mutex.Lock()
 | 
				
			||||||
 | 
						tun.isOpen = false
 | 
				
			||||||
 | 
						tun.mutex.Unlock()
 | 
				
			||||||
 | 
						if tun.iface == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return tun.iface.Close()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
// +build openbsd freebsd netbsd
 | 
					// +build openbsd freebsd netbsd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package yggdrasil
 | 
					package tuntap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/binary"
 | 
						"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
 | 
					// 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
 | 
					// and often doesn't work (if at all), therefore if a call fails, it resorts
 | 
				
			||||||
// to calling "ifconfig" instead.
 | 
					// 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
 | 
						var config water.Config
 | 
				
			||||||
	if ifname[:4] == "auto" {
 | 
						if ifname[:4] == "auto" {
 | 
				
			||||||
		ifname = "/dev/tap0"
 | 
							ifname = "/dev/tap0"
 | 
				
			||||||
| 
						 | 
					@ -103,20 +103,20 @@ func (tun *tunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int
 | 
				
			||||||
	return tun.setupAddress(addr)
 | 
						return tun.setupAddress(addr)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (tun *tunAdapter) setupAddress(addr string) error {
 | 
					func (tun *TunAdapter) setupAddress(addr string) error {
 | 
				
			||||||
	var sfd int
 | 
						var sfd int
 | 
				
			||||||
	var err error
 | 
						var err 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.core.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.core.log.Infof("Interface name: %s", tun.iface.Name())
 | 
						tun.Log.Infof("Interface name: %s", tun.iface.Name())
 | 
				
			||||||
	tun.core.log.Infof("Interface IPv6: %s", addr)
 | 
						tun.Log.Infof("Interface IPv6: %s", addr)
 | 
				
			||||||
	tun.core.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.core.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.core.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.core.log.Errorf("SIOCSIFMTU fallback failed: %v.", err)
 | 
								tun.Log.Errorf("SIOCSIFMTU fallback failed: %v.", err)
 | 
				
			||||||
			tun.core.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.core.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.core.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.core.log.Errorf("SIOCSIFADDR_IN6 fallback failed: %v.", err)
 | 
								tun.Log.Errorf("SIOCSIFADDR_IN6 fallback failed: %v.", err)
 | 
				
			||||||
			tun.core.log.Traceln(string(output))
 | 
								tun.Log.Traceln(string(output))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
// +build !mobile
 | 
					// +build !mobile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package yggdrasil
 | 
					package tuntap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The darwin platform specific tun parts
 | 
					// The darwin platform specific tun parts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,9 +16,9 @@ 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.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}
 | 
						config := water.Config{DeviceType: water.TUN}
 | 
				
			||||||
	iface, err := water.New(config)
 | 
						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
 | 
					// 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.
 | 
					// 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 fd int
 | 
				
			||||||
	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.core.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.core.log.Infof("Interface name: %s", ar.ifra_name)
 | 
						tun.Log.Infof("Interface name: %s", ar.ifra_name)
 | 
				
			||||||
	tun.core.log.Infof("Interface IPv6: %s", addr)
 | 
						tun.Log.Infof("Interface IPv6: %s", addr)
 | 
				
			||||||
	tun.core.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.core.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.core.log.Errorf("Error in SIOCSIFMTU: %v", errno)
 | 
							tun.Log.Errorf("Error in SIOCSIFMTU: %v", errno)
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,19 +1,19 @@
 | 
				
			||||||
// +build mobile
 | 
					// +build mobile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package yggdrasil
 | 
					package tuntap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This is to catch unsupported platforms
 | 
					// This is to catch unsupported platforms
 | 
				
			||||||
// If your platform supports tun devices, you could try configuring it manually
 | 
					// 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
 | 
					// Creates the TUN/TAP adapter, if supported by the Water library. Note that
 | 
				
			||||||
// no guarantees are made at this point on an unsupported platform.
 | 
					// 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)
 | 
						tun.mtu = getSupportedMTU(mtu)
 | 
				
			||||||
	return tun.setupAddress(addr)
 | 
						return tun.setupAddress(addr)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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 {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
// +build !mobile
 | 
					// +build !mobile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package yggdrasil
 | 
					package tuntap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The linux platform specific tun parts
 | 
					// The linux platform specific tun parts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Configures the TAP adapter with the correct IPv6 address and MTU.
 | 
					// 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
 | 
						var config water.Config
 | 
				
			||||||
	if iftapmode {
 | 
						if iftapmode {
 | 
				
			||||||
		config = water.Config{DeviceType: water.TAP}
 | 
							config = water.Config{DeviceType: water.TAP}
 | 
				
			||||||
| 
						 | 
					@ -40,9 +40,9 @@ func (tun *tunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Friendly output
 | 
						// Friendly output
 | 
				
			||||||
	tun.core.log.Infof("Interface name: %s", tun.iface.Name())
 | 
						tun.Log.Infof("Interface name: %s", tun.iface.Name())
 | 
				
			||||||
	tun.core.log.Infof("Interface IPv6: %s", addr)
 | 
						tun.Log.Infof("Interface IPv6: %s", addr)
 | 
				
			||||||
	tun.core.log.Infof("Interface MTU: %d", tun.mtu)
 | 
						tun.Log.Infof("Interface MTU: %d", tun.mtu)
 | 
				
			||||||
	return tun.setupAddress(addr)
 | 
						return tun.setupAddress(addr)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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"
 | 
					// 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
 | 
					// to exist on the system, but this will fail if Netlink is not present in the
 | 
				
			||||||
// kernel (it nearly always is).
 | 
					// kernel (it nearly always is).
 | 
				
			||||||
func (tun *tunAdapter) setupAddress(addr string) error {
 | 
					func (tun *TunAdapter) setupAddress(addr string) error {
 | 
				
			||||||
	// Set address
 | 
						// Set address
 | 
				
			||||||
	var netIF *net.Interface
 | 
						var netIF *net.Interface
 | 
				
			||||||
	ifces, err := net.Interfaces()
 | 
						ifces, err := net.Interfaces()
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
// +build !linux,!darwin,!windows,!openbsd,!freebsd,!netbsd,!mobile
 | 
					// +build !linux,!darwin,!windows,!openbsd,!freebsd,!netbsd,!mobile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package yggdrasil
 | 
					package tuntap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import water "github.com/yggdrasil-network/water"
 | 
					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
 | 
					// Creates the TUN/TAP adapter, if supported by the Water library. Note that
 | 
				
			||||||
// no guarantees are made at this point on an unsupported platform.
 | 
					// 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
 | 
						var config water.Config
 | 
				
			||||||
	if iftapmode {
 | 
						if iftapmode {
 | 
				
			||||||
		config = water.Config{DeviceType: water.TAP}
 | 
							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
 | 
					// 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.core.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
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package yggdrasil
 | 
					package tuntap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
| 
						 | 
					@ -13,9 +13,9 @@ import (
 | 
				
			||||||
// Configures the TAP adapter with the correct IPv6 address and MTU. On Windows
 | 
					// 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
 | 
					// we don't make use of a direct operating system API to do this - we instead
 | 
				
			||||||
// 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.core.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.core.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.core.log.Errorf("Windows netsh failed: %v.", err)
 | 
							tun.Log.Errorf("Windows netsh failed: %v.", err)
 | 
				
			||||||
		tun.core.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.core.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.core.log.Errorf("Windows netsh failed: %v.", err)
 | 
							tun.Log.Errorf("Windows netsh failed: %v.", err)
 | 
				
			||||||
		tun.core.log.Traceln(string(output))
 | 
							tun.Log.Traceln(string(output))
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Get a new iface
 | 
						// Get a new iface
 | 
				
			||||||
| 
						 | 
					@ -58,41 +58,41 @@ func (tun *tunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int
 | 
				
			||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Friendly output
 | 
						// Friendly output
 | 
				
			||||||
	tun.core.log.Infof("Interface name: %s", tun.iface.Name())
 | 
						tun.Log.Infof("Interface name: %s", tun.iface.Name())
 | 
				
			||||||
	tun.core.log.Infof("Interface IPv6: %s", addr)
 | 
						tun.Log.Infof("Interface IPv6: %s", addr)
 | 
				
			||||||
	tun.core.log.Infof("Interface MTU: %d", tun.mtu)
 | 
						tun.Log.Infof("Interface MTU: %d", tun.mtu)
 | 
				
			||||||
	return tun.setupAddress(addr)
 | 
						return tun.setupAddress(addr)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Sets the MTU of the TAP adapter.
 | 
					// Sets the MTU of the TAP adapter.
 | 
				
			||||||
func (tun *tunAdapter) setupMTU(mtu int) error {
 | 
					func (tun *TunAdapter) setupMTU(mtu int) error {
 | 
				
			||||||
	// Set MTU
 | 
						// Set MTU
 | 
				
			||||||
	cmd := exec.Command("netsh", "interface", "ipv6", "set", "subinterface",
 | 
						cmd := exec.Command("netsh", "interface", "ipv6", "set", "subinterface",
 | 
				
			||||||
		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.core.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.core.log.Errorf("Windows netsh failed: %v.", err)
 | 
							tun.Log.Errorf("Windows netsh failed: %v.", err)
 | 
				
			||||||
		tun.core.log.Traceln(string(output))
 | 
							tun.Log.Traceln(string(output))
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Sets the IPv6 address of the TAP adapter.
 | 
					// Sets the IPv6 address of the TAP adapter.
 | 
				
			||||||
func (tun *tunAdapter) setupAddress(addr string) error {
 | 
					func (tun *TunAdapter) setupAddress(addr string) error {
 | 
				
			||||||
	// Set address
 | 
						// Set address
 | 
				
			||||||
	cmd := exec.Command("netsh", "interface", "ipv6", "add", "address",
 | 
						cmd := exec.Command("netsh", "interface", "ipv6", "add", "address",
 | 
				
			||||||
		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.core.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.core.log.Errorf("Windows netsh failed: %v.", err)
 | 
							tun.Log.Errorf("Windows netsh failed: %v.", err)
 | 
				
			||||||
		tun.core.log.Traceln(string(output))
 | 
							tun.Log.Traceln(string(output))
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
| 
						 | 
					@ -1,18 +1,47 @@
 | 
				
			||||||
package yggdrasil
 | 
					package yggdrasil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Defines the minimum required struct members for an adapter type (this is
 | 
					import (
 | 
				
			||||||
// now the base type for tunAdapter in tun.go)
 | 
						"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 {
 | 
					type Adapter struct {
 | 
				
			||||||
	core        *Core
 | 
						adapterImplementation
 | 
				
			||||||
	send        chan<- []byte
 | 
						Core        *Core
 | 
				
			||||||
	recv        <-chan []byte
 | 
						Config      *config.NodeState
 | 
				
			||||||
	reconfigure chan chan error
 | 
						Log         *log.Logger
 | 
				
			||||||
 | 
						Send        chan<- []byte
 | 
				
			||||||
 | 
						Recv        <-chan []byte
 | 
				
			||||||
 | 
						Reject      <-chan RejectedPacket
 | 
				
			||||||
 | 
						Reconfigure chan chan error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Initialises the adapter.
 | 
					// Defines the minimum required functions for an adapter type. Note that the
 | 
				
			||||||
func (adapter *Adapter) init(core *Core, send chan<- []byte, recv <-chan []byte) {
 | 
					// implementation of Init() should call Adapter.Init(). This is not exported
 | 
				
			||||||
	adapter.core = core
 | 
					// because doing so breaks the gomobile bindings for iOS/Android.
 | 
				
			||||||
	adapter.send = send
 | 
					type adapterImplementation interface {
 | 
				
			||||||
	adapter.recv = recv
 | 
						Init(*config.NodeState, *log.Logger, chan<- []byte, <-chan []byte, <-chan RejectedPacket)
 | 
				
			||||||
	adapter.reconfigure = make(chan chan error, 1)
 | 
						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,6 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: Add authentication
 | 
					// TODO: Add authentication
 | 
				
			||||||
| 
						 | 
					@ -58,19 +57,17 @@ func (a *admin) init(c *Core) {
 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			e := <-a.reconfigure
 | 
								e := <-a.reconfigure
 | 
				
			||||||
			a.core.configMutex.RLock()
 | 
								current, previous := a.core.config.Get()
 | 
				
			||||||
			if a.core.config.AdminListen != a.core.configOld.AdminListen {
 | 
								if current.AdminListen != previous.AdminListen {
 | 
				
			||||||
				a.listenaddr = a.core.config.AdminListen
 | 
									a.listenaddr = current.AdminListen
 | 
				
			||||||
				a.close()
 | 
									a.close()
 | 
				
			||||||
				a.start()
 | 
									a.start()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			a.core.configMutex.RUnlock()
 | 
					 | 
				
			||||||
			e <- nil
 | 
								e <- nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
	a.core.configMutex.RLock()
 | 
						current, _ := a.core.config.Get()
 | 
				
			||||||
	a.listenaddr = a.core.config.AdminListen
 | 
						a.listenaddr = current.AdminListen
 | 
				
			||||||
	a.core.configMutex.RUnlock()
 | 
					 | 
				
			||||||
	a.addHandler("list", []string{}, func(in admin_info) (admin_info, error) {
 | 
						a.addHandler("list", []string{}, func(in admin_info) (admin_info, error) {
 | 
				
			||||||
		handlers := make(map[string]interface{})
 | 
							handlers := make(map[string]interface{})
 | 
				
			||||||
		for _, handler := range a.handlers {
 | 
							for _, handler := range a.handlers {
 | 
				
			||||||
| 
						 | 
					@ -171,54 +168,54 @@ func (a *admin) init(c *Core) {
 | 
				
			||||||
			}, errors.New("Failed to remove peer")
 | 
								}, errors.New("Failed to remove peer")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	a.addHandler("getTunTap", []string{}, func(in admin_info) (r admin_info, e error) {
 | 
						/*	a.addHandler("getTunTap", []string{}, func(in admin_info) (r admin_info, e error) {
 | 
				
			||||||
		defer func() {
 | 
								defer func() {
 | 
				
			||||||
			if err := recover(); err != nil {
 | 
									if err := recover(); err != nil {
 | 
				
			||||||
				r = admin_info{"none": admin_info{}}
 | 
										r = admin_info{"none": admin_info{}}
 | 
				
			||||||
				e = nil
 | 
										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{
 | 
								return admin_info{
 | 
				
			||||||
				a.core.router.tun.iface.Name(): admin_info{
 | 
									a.core.router.tun.iface.Name(): admin_info{
 | 
				
			||||||
					"tap_mode": a.core.router.tun.iface.IsTAP(),
 | 
										"tap_mode": a.core.router.tun.iface.IsTAP(),
 | 
				
			||||||
					"mtu":      ifmtu,
 | 
										"mtu":      a.core.router.tun.mtu,
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			}, nil
 | 
								}, nil
 | 
				
			||||||
		}
 | 
							})
 | 
				
			||||||
	})
 | 
							a.addHandler("setTunTap", []string{"name", "[tap_mode]", "[mtu]"}, func(in admin_info) (admin_info, error) {
 | 
				
			||||||
	a.addHandler("getMulticastInterfaces", []string{}, 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
 | 
							var intfs []string
 | 
				
			||||||
		for _, v := range a.core.multicast.interfaces() {
 | 
							for _, v := range a.core.multicast.interfaces() {
 | 
				
			||||||
			intfs = append(intfs, v.Name)
 | 
								intfs = append(intfs, v.Name)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return admin_info{"multicast_interfaces": intfs}, nil
 | 
							return admin_info{"multicast_interfaces": intfs}, nil
 | 
				
			||||||
	})
 | 
						})*/
 | 
				
			||||||
	a.addHandler("getAllowedEncryptionPublicKeys", []string{}, func(in admin_info) (admin_info, error) {
 | 
						a.addHandler("getAllowedEncryptionPublicKeys", []string{}, func(in admin_info) (admin_info, error) {
 | 
				
			||||||
		return admin_info{"allowed_box_pubs": a.getAllowedEncryptionPublicKeys()}, nil
 | 
							return admin_info{"allowed_box_pubs": a.getAllowedEncryptionPublicKeys()}, nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
| 
						 | 
					@ -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.
 | 
					// 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 {
 | 
					func (a *admin) startTunWithMTU(ifname string, iftapmode bool, ifmtu int) error {
 | 
				
			||||||
	// Close the TUN first if open
 | 
						// Close the TUN first if open
 | 
				
			||||||
	_ = a.core.router.tun.close()
 | 
						_ = 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()
 | 
						go a.core.router.tun.write()
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getData_getSelf returns the self node's info for admin responses.
 | 
					// getData_getSelf returns the self node's info for admin responses.
 | 
				
			||||||
func (a *admin) getData_getSelf() *admin_nodeInfo {
 | 
					func (a *admin) getData_getSelf() *admin_nodeInfo {
 | 
				
			||||||
| 
						 | 
					@ -643,14 +642,14 @@ func (a *admin) getData_getSelf() *admin_nodeInfo {
 | 
				
			||||||
	coords := table.self.getCoords()
 | 
						coords := table.self.getCoords()
 | 
				
			||||||
	self := admin_nodeInfo{
 | 
						self := admin_nodeInfo{
 | 
				
			||||||
		{"box_pub_key", hex.EncodeToString(a.core.boxPub[:])},
 | 
							{"box_pub_key", hex.EncodeToString(a.core.boxPub[:])},
 | 
				
			||||||
		{"ip", a.core.GetAddress().String()},
 | 
							{"ip", a.core.Address().String()},
 | 
				
			||||||
		{"subnet", a.core.GetSubnet().String()},
 | 
							{"subnet", a.core.Subnet().String()},
 | 
				
			||||||
		{"coords", fmt.Sprint(coords)},
 | 
							{"coords", fmt.Sprint(coords)},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if name := GetBuildName(); name != "unknown" {
 | 
						if name := BuildName(); name != "unknown" {
 | 
				
			||||||
		self = append(self, admin_pair{"build_name", name})
 | 
							self = append(self, admin_pair{"build_name", name})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if version := GetBuildVersion(); version != "unknown" {
 | 
						if version := BuildVersion(); version != "unknown" {
 | 
				
			||||||
		self = append(self, admin_pair{"build_version", version})
 | 
							self = append(self, admin_pair{"build_version", version})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,25 +55,24 @@ func (c *cryptokey) init(core *Core) {
 | 
				
			||||||
// Configure the CKR routes - this must only ever be called from the router
 | 
					// Configure the CKR routes - this must only ever be called from the router
 | 
				
			||||||
// goroutine, e.g. through router.doAdmin
 | 
					// goroutine, e.g. through router.doAdmin
 | 
				
			||||||
func (c *cryptokey) configure() error {
 | 
					func (c *cryptokey) configure() error {
 | 
				
			||||||
	c.core.configMutex.RLock()
 | 
						current, _ := c.core.config.Get()
 | 
				
			||||||
	defer c.core.configMutex.RUnlock()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set enabled/disabled state
 | 
						// Set enabled/disabled state
 | 
				
			||||||
	c.setEnabled(c.core.config.TunnelRouting.Enable)
 | 
						c.setEnabled(current.TunnelRouting.Enable)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Clear out existing routes
 | 
						// Clear out existing routes
 | 
				
			||||||
	c.ipv6routes = make([]cryptokey_route, 0)
 | 
						c.ipv6routes = make([]cryptokey_route, 0)
 | 
				
			||||||
	c.ipv4routes = make([]cryptokey_route, 0)
 | 
						c.ipv4routes = make([]cryptokey_route, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add IPv6 routes
 | 
						// 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 {
 | 
							if err := c.addRoute(ipv6, pubkey); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add IPv4 routes
 | 
						// 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 {
 | 
							if err := c.addRoute(ipv4, pubkey); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -85,7 +84,7 @@ func (c *cryptokey) configure() error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add IPv6 sources
 | 
						// Add IPv6 sources
 | 
				
			||||||
	c.ipv6sources = make([]net.IPNet, 0)
 | 
						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 {
 | 
							if err := c.addSourceSubnet(source); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -93,7 +92,7 @@ func (c *cryptokey) configure() error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add IPv4 sources
 | 
						// Add IPv4 sources
 | 
				
			||||||
	c.ipv4sources = make([]net.IPNet, 0)
 | 
						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 {
 | 
							if err := c.addSourceSubnet(source); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,9 +2,9 @@ package yggdrasil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"sync"
 | 
					 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gologme/log"
 | 
						"github.com/gologme/log"
 | 
				
			||||||
| 
						 | 
					@ -12,26 +12,18 @@ import (
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var buildName string
 | 
					var buildName string
 | 
				
			||||||
var buildVersion string
 | 
					var buildVersion string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type module interface {
 | 
					 | 
				
			||||||
	init(*Core, *config.NodeConfig) error
 | 
					 | 
				
			||||||
	start() error
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The Core object represents the Yggdrasil node. You should create a Core
 | 
					// The Core object represents the Yggdrasil node. You should create a Core
 | 
				
			||||||
// object for each Yggdrasil node you plan to run.
 | 
					// object for each Yggdrasil node you plan to run.
 | 
				
			||||||
type Core struct {
 | 
					type Core struct {
 | 
				
			||||||
	// This is the main data structure that holds everything else for a node
 | 
						// 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
 | 
						// 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
 | 
						// guarantee that it will be covered by the mutex
 | 
				
			||||||
	config      config.NodeConfig // Active config
 | 
						config      config.NodeState // Config
 | 
				
			||||||
	configOld   config.NodeConfig // Previous config
 | 
					 | 
				
			||||||
	configMutex sync.RWMutex      // Protects both config and configOld
 | 
					 | 
				
			||||||
	boxPub      crypto.BoxPubKey
 | 
						boxPub      crypto.BoxPubKey
 | 
				
			||||||
	boxPriv     crypto.BoxPrivKey
 | 
						boxPriv     crypto.BoxPrivKey
 | 
				
			||||||
	sigPub      crypto.SigPubKey
 | 
						sigPub      crypto.SigPubKey
 | 
				
			||||||
| 
						 | 
					@ -43,7 +35,6 @@ type Core struct {
 | 
				
			||||||
	dht         dht
 | 
						dht         dht
 | 
				
			||||||
	admin       admin
 | 
						admin       admin
 | 
				
			||||||
	searches    searches
 | 
						searches    searches
 | 
				
			||||||
	multicast   multicast
 | 
					 | 
				
			||||||
	link        link
 | 
						link        link
 | 
				
			||||||
	log         *log.Logger
 | 
						log         *log.Logger
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -57,19 +48,21 @@ func (c *Core) init() error {
 | 
				
			||||||
		c.log = log.New(ioutil.Discard, "", 0)
 | 
							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 {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	boxPrivHex, err := hex.DecodeString(c.config.EncryptionPrivateKey)
 | 
						boxPrivHex, err := hex.DecodeString(current.EncryptionPrivateKey)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sigPubHex, err := hex.DecodeString(c.config.SigningPublicKey)
 | 
						sigPubHex, err := hex.DecodeString(current.SigningPublicKey)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sigPrivHex, err := hex.DecodeString(c.config.SigningPrivateKey)
 | 
						sigPrivHex, err := hex.DecodeString(current.SigningPrivateKey)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -83,7 +76,7 @@ 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.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?
 | 
				
			||||||
| 
						 | 
					@ -96,20 +89,17 @@ func (c *Core) init() error {
 | 
				
			||||||
// be reconnected with.
 | 
					// be reconnected with.
 | 
				
			||||||
func (c *Core) addPeerLoop() {
 | 
					func (c *Core) addPeerLoop() {
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		// Get the peers from the config - these could change!
 | 
							//  the peers from the config - these could change!
 | 
				
			||||||
		c.configMutex.RLock()
 | 
							current, _ := c.config.Get()
 | 
				
			||||||
		peers := c.config.Peers
 | 
					 | 
				
			||||||
		interfacepeers := c.config.InterfacePeers
 | 
					 | 
				
			||||||
		c.configMutex.RUnlock()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Add peers from the Peers section
 | 
							// Add peers from the Peers section
 | 
				
			||||||
		for _, peer := range peers {
 | 
							for _, peer := range current.Peers {
 | 
				
			||||||
			c.AddPeer(peer, "")
 | 
								c.AddPeer(peer, "")
 | 
				
			||||||
			time.Sleep(time.Second)
 | 
								time.Sleep(time.Second)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Add peers from the InterfacePeers section
 | 
							// Add peers from the InterfacePeers section
 | 
				
			||||||
		for intf, intfpeers := range interfacepeers {
 | 
							for intf, intfpeers := range current.InterfacePeers {
 | 
				
			||||||
			for _, peer := range intfpeers {
 | 
								for _, peer := range intfpeers {
 | 
				
			||||||
				c.AddPeer(peer, intf)
 | 
									c.AddPeer(peer, intf)
 | 
				
			||||||
				time.Sleep(time.Second)
 | 
									time.Sleep(time.Second)
 | 
				
			||||||
| 
						 | 
					@ -121,15 +111,13 @@ func (c *Core) addPeerLoop() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpdateConfig updates the configuration in Core and then signals the
 | 
					// UpdateConfig updates the configuration in Core with the provided
 | 
				
			||||||
// various module goroutines to reconfigure themselves if needed
 | 
					// config.NodeConfig and then signals the various module goroutines to
 | 
				
			||||||
 | 
					// reconfigure themselves if needed.
 | 
				
			||||||
func (c *Core) UpdateConfig(config *config.NodeConfig) {
 | 
					func (c *Core) UpdateConfig(config *config.NodeConfig) {
 | 
				
			||||||
	c.log.Infoln("Reloading configuration...")
 | 
						c.log.Infoln("Reloading configuration...")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c.configMutex.Lock()
 | 
						c.config.Replace(*config)
 | 
				
			||||||
	c.configOld = c.config
 | 
					 | 
				
			||||||
	c.config = *config
 | 
					 | 
				
			||||||
	c.configMutex.Unlock()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	errors := 0
 | 
						errors := 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,11 +128,9 @@ func (c *Core) UpdateConfig(config *config.NodeConfig) {
 | 
				
			||||||
		c.sessions.reconfigure,
 | 
							c.sessions.reconfigure,
 | 
				
			||||||
		c.peers.reconfigure,
 | 
							c.peers.reconfigure,
 | 
				
			||||||
		c.router.reconfigure,
 | 
							c.router.reconfigure,
 | 
				
			||||||
		c.router.tun.reconfigure,
 | 
					 | 
				
			||||||
		c.router.cryptokey.reconfigure,
 | 
							c.router.cryptokey.reconfigure,
 | 
				
			||||||
		c.switchTable.reconfigure,
 | 
							c.switchTable.reconfigure,
 | 
				
			||||||
		c.link.reconfigure,
 | 
							c.link.reconfigure,
 | 
				
			||||||
		c.multicast.reconfigure,
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, component := range components {
 | 
						for _, component := range components {
 | 
				
			||||||
| 
						 | 
					@ -163,190 +149,219 @@ func (c *Core) UpdateConfig(config *config.NodeConfig) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetBuildName gets the current build name. This is usually injected if built
 | 
					// BuildName gets the current build name. This is usually injected if built
 | 
				
			||||||
// from git, or returns "unknown" otherwise.
 | 
					// from git, or returns "unknown" otherwise.
 | 
				
			||||||
func GetBuildName() string {
 | 
					func BuildName() string {
 | 
				
			||||||
	if buildName == "" {
 | 
						if buildName == "" {
 | 
				
			||||||
		return "unknown"
 | 
							return "unknown"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return buildName
 | 
						return buildName
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get the current build version. This is usually injected if built from git,
 | 
					// BuildVersion gets the current build version. This is usually injected if
 | 
				
			||||||
// or returns "unknown" otherwise.
 | 
					// built from git, or returns "unknown" otherwise.
 | 
				
			||||||
func GetBuildVersion() string {
 | 
					func BuildVersion() string {
 | 
				
			||||||
	if buildVersion == "" {
 | 
						if buildVersion == "" {
 | 
				
			||||||
		return "unknown"
 | 
							return "unknown"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return buildVersion
 | 
						return buildVersion
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Starts up Yggdrasil using the provided NodeConfig, and outputs debug logging
 | 
					// SetRouterAdapter instructs Yggdrasil to use the given adapter when starting
 | 
				
			||||||
// through the provided log.Logger. The started stack will include TCP and UDP
 | 
					// the router. The adapter must implement the standard
 | 
				
			||||||
// sockets, a multicast discovery socket, an admin socket, router, switch and
 | 
					// adapter.adapterImplementation interface and should extend the adapter.Adapter
 | 
				
			||||||
// DHT node.
 | 
					// struct.
 | 
				
			||||||
func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
 | 
					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
 | 
				
			||||||
 | 
					// 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. A config.NodeState is returned which contains both the
 | 
				
			||||||
 | 
					// current and previous configurations (from reconfigures).
 | 
				
			||||||
 | 
					func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) (*config.NodeState, error) {
 | 
				
			||||||
	c.log = log
 | 
						c.log = log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if name := GetBuildName(); name != "unknown" {
 | 
						c.config = config.NodeState{
 | 
				
			||||||
 | 
							Current:  *nc,
 | 
				
			||||||
 | 
							Previous: *nc,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if name := BuildName(); name != "unknown" {
 | 
				
			||||||
		c.log.Infoln("Build name:", name)
 | 
							c.log.Infoln("Build name:", name)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if version := GetBuildVersion(); version != "unknown" {
 | 
						if version := BuildVersion(); version != "unknown" {
 | 
				
			||||||
		c.log.Infoln("Build version:", version)
 | 
							c.log.Infoln("Build version:", version)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c.log.Infoln("Starting up...")
 | 
						c.log.Infoln("Starting up...")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c.configMutex.Lock()
 | 
					 | 
				
			||||||
	c.config = *nc
 | 
					 | 
				
			||||||
	c.configOld = c.config
 | 
					 | 
				
			||||||
	c.configMutex.Unlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	c.init()
 | 
						c.init()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := c.link.init(c); err != nil {
 | 
						if err := c.link.init(c); err != nil {
 | 
				
			||||||
		c.log.Errorln("Failed to start link interfaces")
 | 
							c.log.Errorln("Failed to start link interfaces")
 | 
				
			||||||
		return err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if nc.SwitchOptions.MaxTotalQueueSize >= SwitchQueueTotalMinSize {
 | 
						c.config.Mutex.RLock()
 | 
				
			||||||
		c.switchTable.queueTotalMaxSize = nc.SwitchOptions.MaxTotalQueueSize
 | 
						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 {
 | 
						if err := c.switchTable.start(); err != nil {
 | 
				
			||||||
		c.log.Errorln("Failed to start switch")
 | 
							c.log.Errorln("Failed to start switch")
 | 
				
			||||||
		return err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := c.router.start(); err != nil {
 | 
						if err := c.router.start(); err != nil {
 | 
				
			||||||
		c.log.Errorln("Failed to start router")
 | 
							c.log.Errorln("Failed to start router")
 | 
				
			||||||
		return err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := c.admin.start(); err != nil {
 | 
						if err := c.admin.start(); err != nil {
 | 
				
			||||||
		c.log.Errorln("Failed to start admin socket")
 | 
							c.log.Errorln("Failed to start admin socket")
 | 
				
			||||||
		return err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := c.multicast.start(); err != nil {
 | 
						if c.router.adapter != nil {
 | 
				
			||||||
		c.log.Errorln("Failed to start multicast interface")
 | 
							if err := c.router.adapter.Start(c.router.addr, c.router.subnet); err != nil {
 | 
				
			||||||
		return err
 | 
								c.log.Errorln("Failed to start TUN/TAP")
 | 
				
			||||||
	}
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	if err := c.router.tun.start(); err != nil {
 | 
					 | 
				
			||||||
		c.log.Errorln("Failed to start TUN/TAP")
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go c.addPeerLoop()
 | 
						go c.addPeerLoop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c.log.Infoln("Startup complete")
 | 
						c.log.Infoln("Startup complete")
 | 
				
			||||||
	return nil
 | 
						return &c.config, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Stops 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...")
 | 
				
			||||||
	c.router.tun.close()
 | 
						if c.router.adapter != nil {
 | 
				
			||||||
 | 
							c.router.adapter.Close()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	c.admin.close()
 | 
						c.admin.close()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Generates a new encryption keypair. The encryption keys are used to
 | 
					// ListenTCP starts a new TCP listener. The input URI should match that of the
 | 
				
			||||||
// encrypt traffic and to derive the IPv6 address/subnet of the node.
 | 
					// "Listen" configuration item, e.g.
 | 
				
			||||||
 | 
					// 		tcp://a.b.c.d:e
 | 
				
			||||||
 | 
					func (c *Core) ListenTCP(uri string) (*TcpListener, error) {
 | 
				
			||||||
 | 
						return c.link.tcp.listen(uri)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewEncryptionKeys generates a new encryption keypair. The encryption keys are
 | 
				
			||||||
 | 
					// used to encrypt traffic and to derive the IPv6 address/subnet of the node.
 | 
				
			||||||
func (c *Core) NewEncryptionKeys() (*crypto.BoxPubKey, *crypto.BoxPrivKey) {
 | 
					func (c *Core) NewEncryptionKeys() (*crypto.BoxPubKey, *crypto.BoxPrivKey) {
 | 
				
			||||||
	return crypto.NewBoxKeys()
 | 
						return crypto.NewBoxKeys()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Generates a new signing keypair. The signing keys are used to derive the
 | 
					// NewSigningKeys generates a new signing keypair. The signing keys are used to
 | 
				
			||||||
// structure of the spanning tree.
 | 
					// derive the structure of the spanning tree.
 | 
				
			||||||
func (c *Core) NewSigningKeys() (*crypto.SigPubKey, *crypto.SigPrivKey) {
 | 
					func (c *Core) NewSigningKeys() (*crypto.SigPubKey, *crypto.SigPrivKey) {
 | 
				
			||||||
	return crypto.NewSigKeys()
 | 
						return crypto.NewSigKeys()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Gets the node ID.
 | 
					// NodeID gets the node ID.
 | 
				
			||||||
func (c *Core) GetNodeID() *crypto.NodeID {
 | 
					func (c *Core) NodeID() *crypto.NodeID {
 | 
				
			||||||
	return crypto.GetNodeID(&c.boxPub)
 | 
						return crypto.GetNodeID(&c.boxPub)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Gets the tree ID.
 | 
					// TreeID gets the tree ID.
 | 
				
			||||||
func (c *Core) GetTreeID() *crypto.TreeID {
 | 
					func (c *Core) TreeID() *crypto.TreeID {
 | 
				
			||||||
	return crypto.GetTreeID(&c.sigPub)
 | 
						return crypto.GetTreeID(&c.sigPub)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Gets the IPv6 address of the Yggdrasil node. This is always a /128.
 | 
					// SigPubKey gets the node's signing public key.
 | 
				
			||||||
func (c *Core) GetAddress() *net.IP {
 | 
					func (c *Core) SigPubKey() string {
 | 
				
			||||||
	address := net.IP(address.AddrForNodeID(c.GetNodeID())[:])
 | 
						return hex.EncodeToString(c.sigPub[:])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BoxPubKey gets the node's encryption public key.
 | 
				
			||||||
 | 
					func (c *Core) BoxPubKey() string {
 | 
				
			||||||
 | 
						return hex.EncodeToString(c.boxPub[:])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Address gets the IPv6 address of the Yggdrasil node. This is always a /128
 | 
				
			||||||
 | 
					// address.
 | 
				
			||||||
 | 
					func (c *Core) Address() *net.IP {
 | 
				
			||||||
 | 
						address := net.IP(address.AddrForNodeID(c.NodeID())[:])
 | 
				
			||||||
	return &address
 | 
						return &address
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Gets the routed IPv6 subnet of the Yggdrasil node. This is always a /64.
 | 
					// Subnet gets the routed IPv6 subnet of the Yggdrasil node. This is always a
 | 
				
			||||||
func (c *Core) GetSubnet() *net.IPNet {
 | 
					// /64 subnet.
 | 
				
			||||||
	subnet := address.SubnetForNodeID(c.GetNodeID())[:]
 | 
					func (c *Core) Subnet() *net.IPNet {
 | 
				
			||||||
 | 
						subnet := address.SubnetForNodeID(c.NodeID())[:]
 | 
				
			||||||
	subnet = append(subnet, 0, 0, 0, 0, 0, 0, 0, 0)
 | 
						subnet = append(subnet, 0, 0, 0, 0, 0, 0, 0, 0)
 | 
				
			||||||
	return &net.IPNet{IP: subnet, Mask: net.CIDRMask(64, 128)}
 | 
						return &net.IPNet{IP: subnet, Mask: net.CIDRMask(64, 128)}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Gets the nodeinfo.
 | 
					// RouterAddresses returns the raw address and subnet types as used by the
 | 
				
			||||||
func (c *Core) GetNodeInfo() nodeinfoPayload {
 | 
					// router
 | 
				
			||||||
 | 
					func (c *Core) RouterAddresses() (address.Address, address.Subnet) {
 | 
				
			||||||
 | 
						return c.router.addr, c.router.subnet
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NodeInfo gets the currently configured nodeinfo.
 | 
				
			||||||
 | 
					func (c *Core) NodeInfo() nodeinfoPayload {
 | 
				
			||||||
	return c.router.nodeinfo.getNodeInfo()
 | 
						return c.router.nodeinfo.getNodeInfo()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Sets the nodeinfo.
 | 
					// SetNodeInfo the lcal nodeinfo. Note that nodeinfo can be any value or struct,
 | 
				
			||||||
 | 
					// it will be serialised into JSON automatically.
 | 
				
			||||||
func (c *Core) SetNodeInfo(nodeinfo interface{}, nodeinfoprivacy bool) {
 | 
					func (c *Core) SetNodeInfo(nodeinfo interface{}, nodeinfoprivacy bool) {
 | 
				
			||||||
	c.router.nodeinfo.setNodeInfo(nodeinfo, nodeinfoprivacy)
 | 
						c.router.nodeinfo.setNodeInfo(nodeinfo, nodeinfoprivacy)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Sets the output logger of the Yggdrasil node after startup. This may be
 | 
					// SetLogger sets the output logger of the Yggdrasil node after startup. This
 | 
				
			||||||
// useful if you want to redirect the output later.
 | 
					// may be useful if you want to redirect the output later.
 | 
				
			||||||
func (c *Core) SetLogger(log *log.Logger) {
 | 
					func (c *Core) SetLogger(log *log.Logger) {
 | 
				
			||||||
	c.log = log
 | 
						c.log = log
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Adds a peer. This should be specified in the peer URI format, i.e.
 | 
					// AddPeer adds a peer. This should be specified in the peer URI format, e.g.:
 | 
				
			||||||
// tcp://a.b.c.d:e, udp://a.b.c.d:e, socks://a.b.c.d:e/f.g.h.i:j
 | 
					// 		tcp://a.b.c.d:e
 | 
				
			||||||
 | 
					//		socks://a.b.c.d:e/f.g.h.i:j
 | 
				
			||||||
 | 
					// This adds the peer to the peer list, so that they will be called again if the
 | 
				
			||||||
 | 
					// connection drops.
 | 
				
			||||||
func (c *Core) AddPeer(addr string, sintf string) error {
 | 
					func (c *Core) AddPeer(addr string, sintf string) error {
 | 
				
			||||||
	return c.admin.addPeer(addr, sintf)
 | 
						if err := c.CallPeer(addr, sintf); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.config.Mutex.Lock()
 | 
				
			||||||
 | 
						if sintf == "" {
 | 
				
			||||||
 | 
							c.config.Current.Peers = append(c.config.Current.Peers, addr)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							c.config.Current.InterfacePeers[sintf] = append(c.config.Current.InterfacePeers[sintf], addr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.config.Mutex.Unlock()
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Adds an allowed public key. This allow peerings to be restricted only to
 | 
					// CallPeer calls a peer once. This should be specified in the peer URI format,
 | 
				
			||||||
// keys that you have selected.
 | 
					// e.g.:
 | 
				
			||||||
 | 
					// 		tcp://a.b.c.d:e
 | 
				
			||||||
 | 
					//		socks://a.b.c.d:e/f.g.h.i:j
 | 
				
			||||||
 | 
					// This does not add the peer to the peer list, so if the connection drops, the
 | 
				
			||||||
 | 
					// peer will not be called again automatically.
 | 
				
			||||||
 | 
					func (c *Core) CallPeer(addr string, sintf string) error {
 | 
				
			||||||
 | 
						return c.link.call(addr, sintf)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddAllowedEncryptionPublicKey adds an allowed public key. This allow peerings
 | 
				
			||||||
 | 
					// to be restricted only to keys that you have selected.
 | 
				
			||||||
func (c *Core) AddAllowedEncryptionPublicKey(boxStr string) error {
 | 
					func (c *Core) AddAllowedEncryptionPublicKey(boxStr string) error {
 | 
				
			||||||
	return c.admin.addAllowedEncryptionPublicKey(boxStr)
 | 
						return c.admin.addAllowedEncryptionPublicKey(boxStr)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Gets the default admin listen address for your platform.
 | 
					 | 
				
			||||||
func (c *Core) GetAdminDefaultListen() string {
 | 
					 | 
				
			||||||
	return defaults.GetDefaults().DefaultAdminListen
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Gets the default TUN/TAP interface name for your platform.
 | 
					 | 
				
			||||||
func (c *Core) GetTUNDefaultIfName() string {
 | 
					 | 
				
			||||||
	return defaults.GetDefaults().DefaultIfName
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Gets the default TUN/TAP interface MTU for your platform. This can be as high
 | 
					 | 
				
			||||||
// as 65535, depending on platform, but is never lower than 1280.
 | 
					 | 
				
			||||||
func (c *Core) GetTUNDefaultIfMTU() int {
 | 
					 | 
				
			||||||
	return defaults.GetDefaults().DefaultIfMTU
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Gets the maximum supported TUN/TAP interface MTU for your platform. This
 | 
					 | 
				
			||||||
// can be as high as 65535, depending on platform, but is never lower than 1280.
 | 
					 | 
				
			||||||
func (c *Core) GetTUNMaximumIfMTU() int {
 | 
					 | 
				
			||||||
	return defaults.GetDefaults().MaximumIfMTU
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Gets the default TUN/TAP interface mode for your platform.
 | 
					 | 
				
			||||||
func (c *Core) GetTUNDefaultIfTAPMode() bool {
 | 
					 | 
				
			||||||
	return defaults.GetDefaults().DefaultIfTAPMode
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Gets the current TUN/TAP interface name.
 | 
					 | 
				
			||||||
func (c *Core) GetTUNIfName() string {
 | 
					 | 
				
			||||||
	return c.router.tun.iface.Name()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Gets the current TUN/TAP interface MTU.
 | 
					 | 
				
			||||||
func (c *Core) GetTUNIfMTU() int {
 | 
					 | 
				
			||||||
	return c.router.tun.mtu
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,7 +86,7 @@ func (t *dht) init(c *Core) {
 | 
				
			||||||
			e <- nil
 | 
								e <- nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
	t.nodeID = *t.core.GetNodeID()
 | 
						t.nodeID = *t.core.NodeID()
 | 
				
			||||||
	t.peers = make(chan *dhtInfo, 1024)
 | 
						t.peers = make(chan *dhtInfo, 1024)
 | 
				
			||||||
	t.callbacks = make(map[dhtReqKey]dht_callbackInfo)
 | 
						t.callbacks = make(map[dhtReqKey]dht_callbackInfo)
 | 
				
			||||||
	t.reset()
 | 
						t.reset()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,8 +23,7 @@ type link struct {
 | 
				
			||||||
	reconfigure chan chan error
 | 
						reconfigure chan chan error
 | 
				
			||||||
	mutex       sync.RWMutex // protects interfaces below
 | 
						mutex       sync.RWMutex // protects interfaces below
 | 
				
			||||||
	interfaces  map[linkInfo]*linkInterface
 | 
						interfaces  map[linkInfo]*linkInterface
 | 
				
			||||||
	awdl        awdl // AWDL interface support
 | 
						tcp         tcp // TCP interface support
 | 
				
			||||||
	tcp         tcp  // TCP interface support
 | 
					 | 
				
			||||||
	// TODO timeout (to remove from switch), read from config.ReadTimeout
 | 
						// TODO timeout (to remove from switch), read from config.ReadTimeout
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,26 +67,15 @@ func (l *link) init(c *Core) error {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := l.awdl.init(l); err != nil {
 | 
					 | 
				
			||||||
		c.log.Errorln("Failed to start AWDL interface")
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			e := <-l.reconfigure
 | 
								e := <-l.reconfigure
 | 
				
			||||||
			tcpresponse := make(chan error)
 | 
								tcpresponse := make(chan error)
 | 
				
			||||||
			awdlresponse := make(chan error)
 | 
					 | 
				
			||||||
			l.tcp.reconfigure <- tcpresponse
 | 
								l.tcp.reconfigure <- tcpresponse
 | 
				
			||||||
			if err := <-tcpresponse; err != nil {
 | 
								if err := <-tcpresponse; err != nil {
 | 
				
			||||||
				e <- err
 | 
									e <- err
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			l.awdl.reconfigure <- awdlresponse
 | 
					 | 
				
			||||||
			if err := <-awdlresponse; err != nil {
 | 
					 | 
				
			||||||
				e <- err
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			e <- nil
 | 
								e <- nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,130 +0,0 @@
 | 
				
			||||||
// +build mobile
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package yggdrasil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"encoding/hex"
 | 
					 | 
				
			||||||
	"encoding/json"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/gologme/log"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	hjson "github.com/hjson/hjson-go"
 | 
					 | 
				
			||||||
	"github.com/mitchellh/mapstructure"
 | 
					 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
					 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This file is meant to "plug the gap" for mobile support, as Gomobile will
 | 
					 | 
				
			||||||
// not create headers for Swift/Obj-C etc if they have complex (non-native)
 | 
					 | 
				
			||||||
// types. Therefore for iOS we will expose some nice simple functions. Note
 | 
					 | 
				
			||||||
// that in the case of iOS we handle reading/writing to/from TUN in Swift
 | 
					 | 
				
			||||||
// therefore we use the "dummy" TUN interface instead.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Core) addStaticPeers(cfg *config.NodeConfig) {
 | 
					 | 
				
			||||||
	if len(cfg.Peers) == 0 && len(cfg.InterfacePeers) == 0 {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		for _, peer := range cfg.Peers {
 | 
					 | 
				
			||||||
			c.AddPeer(peer, "")
 | 
					 | 
				
			||||||
			time.Sleep(time.Second)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for intf, intfpeers := range cfg.InterfacePeers {
 | 
					 | 
				
			||||||
			for _, peer := range intfpeers {
 | 
					 | 
				
			||||||
				c.AddPeer(peer, intf)
 | 
					 | 
				
			||||||
				time.Sleep(time.Second)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		time.Sleep(time.Minute)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Starts a node with a randomly generated config.
 | 
					 | 
				
			||||||
func (c *Core) StartAutoconfigure() error {
 | 
					 | 
				
			||||||
	mobilelog := MobileLogger{}
 | 
					 | 
				
			||||||
	logger := log.New(mobilelog, "", 0)
 | 
					 | 
				
			||||||
	nc := config.GenerateConfig()
 | 
					 | 
				
			||||||
	nc.IfName = "dummy"
 | 
					 | 
				
			||||||
	nc.AdminListen = "tcp://localhost:9001"
 | 
					 | 
				
			||||||
	nc.Peers = []string{}
 | 
					 | 
				
			||||||
	if hostname, err := os.Hostname(); err == nil {
 | 
					 | 
				
			||||||
		nc.NodeInfo = map[string]interface{}{"name": hostname}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := c.Start(nc, logger); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	go c.addStaticPeers(nc)
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Starts a node with the given JSON config. You can get JSON config (rather
 | 
					 | 
				
			||||||
// than HJSON) by using the GenerateConfigJSON() function.
 | 
					 | 
				
			||||||
func (c *Core) StartJSON(configjson []byte) error {
 | 
					 | 
				
			||||||
	mobilelog := MobileLogger{}
 | 
					 | 
				
			||||||
	logger := log.New(mobilelog, "", 0)
 | 
					 | 
				
			||||||
	nc := config.GenerateConfig()
 | 
					 | 
				
			||||||
	var dat map[string]interface{}
 | 
					 | 
				
			||||||
	if err := hjson.Unmarshal(configjson, &dat); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := mapstructure.Decode(dat, &nc); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nc.IfName = "dummy"
 | 
					 | 
				
			||||||
	if err := c.Start(nc, logger); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	go c.addStaticPeers(nc)
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Generates mobile-friendly configuration in JSON format.
 | 
					 | 
				
			||||||
func GenerateConfigJSON() []byte {
 | 
					 | 
				
			||||||
	nc := config.GenerateConfig()
 | 
					 | 
				
			||||||
	nc.IfName = "dummy"
 | 
					 | 
				
			||||||
	if json, err := json.Marshal(nc); err == nil {
 | 
					 | 
				
			||||||
		return json
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Gets the node's IPv6 address.
 | 
					 | 
				
			||||||
func (c *Core) GetAddressString() string {
 | 
					 | 
				
			||||||
	return c.GetAddress().String()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Gets the node's IPv6 subnet in CIDR notation.
 | 
					 | 
				
			||||||
func (c *Core) GetSubnetString() string {
 | 
					 | 
				
			||||||
	return c.GetSubnet().String()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Gets the node's public encryption key.
 | 
					 | 
				
			||||||
func (c *Core) GetBoxPubKeyString() string {
 | 
					 | 
				
			||||||
	return hex.EncodeToString(c.boxPub[:])
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Gets the node's public signing key.
 | 
					 | 
				
			||||||
func (c *Core) GetSigPubKeyString() string {
 | 
					 | 
				
			||||||
	return hex.EncodeToString(c.sigPub[:])
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Wait for a packet from the router. You will use this when implementing a
 | 
					 | 
				
			||||||
// dummy adapter in place of real TUN - when this call returns a packet, you
 | 
					 | 
				
			||||||
// will probably want to give it to the OS to write to TUN.
 | 
					 | 
				
			||||||
func (c *Core) RouterRecvPacket() ([]byte, error) {
 | 
					 | 
				
			||||||
	packet := <-c.router.tun.recv
 | 
					 | 
				
			||||||
	return packet, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Send a packet to the router. You will use this when implementing a
 | 
					 | 
				
			||||||
// dummy adapter in place of real TUN - when the operating system tells you
 | 
					 | 
				
			||||||
// that a new packet is available from TUN, call this function to give it to
 | 
					 | 
				
			||||||
// Yggdrasil.
 | 
					 | 
				
			||||||
func (c *Core) RouterSendPacket(buf []byte) error {
 | 
					 | 
				
			||||||
	packet := append(util.GetBytes(), buf[:]...)
 | 
					 | 
				
			||||||
	c.router.tun.send <- packet
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -101,8 +101,8 @@ func (m *nodeinfo) setNodeInfo(given interface{}, privacy bool) error {
 | 
				
			||||||
	m.myNodeInfoMutex.Lock()
 | 
						m.myNodeInfoMutex.Lock()
 | 
				
			||||||
	defer m.myNodeInfoMutex.Unlock()
 | 
						defer m.myNodeInfoMutex.Unlock()
 | 
				
			||||||
	defaults := map[string]interface{}{
 | 
						defaults := map[string]interface{}{
 | 
				
			||||||
		"buildname":     GetBuildName(),
 | 
							"buildname":     BuildName(),
 | 
				
			||||||
		"buildversion":  GetBuildVersion(),
 | 
							"buildversion":  BuildVersion(),
 | 
				
			||||||
		"buildplatform": runtime.GOOS,
 | 
							"buildplatform": runtime.GOOS,
 | 
				
			||||||
		"buildarch":     runtime.GOARCH,
 | 
							"buildarch":     runtime.GOARCH,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,42 +44,42 @@ func (ps *peers) init(c *Core) {
 | 
				
			||||||
// because the key is in the whitelist or because the whitelist is empty.
 | 
					// because the key is in the whitelist or because the whitelist is empty.
 | 
				
			||||||
func (ps *peers) isAllowedEncryptionPublicKey(box *crypto.BoxPubKey) bool {
 | 
					func (ps *peers) isAllowedEncryptionPublicKey(box *crypto.BoxPubKey) bool {
 | 
				
			||||||
	boxstr := hex.EncodeToString(box[:])
 | 
						boxstr := hex.EncodeToString(box[:])
 | 
				
			||||||
	ps.core.configMutex.RLock()
 | 
						ps.core.config.Mutex.RLock()
 | 
				
			||||||
	defer ps.core.configMutex.RUnlock()
 | 
						defer ps.core.config.Mutex.RUnlock()
 | 
				
			||||||
	for _, v := range ps.core.config.AllowedEncryptionPublicKeys {
 | 
						for _, v := range ps.core.config.Current.AllowedEncryptionPublicKeys {
 | 
				
			||||||
		if v == boxstr {
 | 
							if v == boxstr {
 | 
				
			||||||
			return true
 | 
								return true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return len(ps.core.config.AllowedEncryptionPublicKeys) == 0
 | 
						return len(ps.core.config.Current.AllowedEncryptionPublicKeys) == 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Adds a key to the whitelist.
 | 
					// Adds a key to the whitelist.
 | 
				
			||||||
func (ps *peers) addAllowedEncryptionPublicKey(box string) {
 | 
					func (ps *peers) addAllowedEncryptionPublicKey(box string) {
 | 
				
			||||||
	ps.core.configMutex.RLock()
 | 
						ps.core.config.Mutex.RLock()
 | 
				
			||||||
	defer ps.core.configMutex.RUnlock()
 | 
						defer ps.core.config.Mutex.RUnlock()
 | 
				
			||||||
	ps.core.config.AllowedEncryptionPublicKeys =
 | 
						ps.core.config.Current.AllowedEncryptionPublicKeys =
 | 
				
			||||||
		append(ps.core.config.AllowedEncryptionPublicKeys, box)
 | 
							append(ps.core.config.Current.AllowedEncryptionPublicKeys, box)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Removes a key from the whitelist.
 | 
					// Removes a key from the whitelist.
 | 
				
			||||||
func (ps *peers) removeAllowedEncryptionPublicKey(box string) {
 | 
					func (ps *peers) removeAllowedEncryptionPublicKey(box string) {
 | 
				
			||||||
	ps.core.configMutex.RLock()
 | 
						ps.core.config.Mutex.RLock()
 | 
				
			||||||
	defer ps.core.configMutex.RUnlock()
 | 
						defer ps.core.config.Mutex.RUnlock()
 | 
				
			||||||
	for k, v := range ps.core.config.AllowedEncryptionPublicKeys {
 | 
						for k, v := range ps.core.config.Current.AllowedEncryptionPublicKeys {
 | 
				
			||||||
		if v == box {
 | 
							if v == box {
 | 
				
			||||||
			ps.core.config.AllowedEncryptionPublicKeys =
 | 
								ps.core.config.Current.AllowedEncryptionPublicKeys =
 | 
				
			||||||
				append(ps.core.config.AllowedEncryptionPublicKeys[:k],
 | 
									append(ps.core.config.Current.AllowedEncryptionPublicKeys[:k],
 | 
				
			||||||
					ps.core.config.AllowedEncryptionPublicKeys[k+1:]...)
 | 
										ps.core.config.Current.AllowedEncryptionPublicKeys[k+1:]...)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Gets the whitelist of allowed keys for incoming connections.
 | 
					// Gets the whitelist of allowed keys for incoming connections.
 | 
				
			||||||
func (ps *peers) getAllowedEncryptionPublicKeys() []string {
 | 
					func (ps *peers) getAllowedEncryptionPublicKeys() []string {
 | 
				
			||||||
	ps.core.configMutex.RLock()
 | 
						ps.core.config.Mutex.RLock()
 | 
				
			||||||
	defer ps.core.configMutex.RUnlock()
 | 
						defer ps.core.config.Mutex.RUnlock()
 | 
				
			||||||
	return ps.core.config.AllowedEncryptionPublicKeys
 | 
						return ps.core.config.Current.AllowedEncryptionPublicKeys
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Atomically gets a map[switchPort]*peer of known peers.
 | 
					// Atomically gets a map[switchPort]*peer of known peers.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@ package yggdrasil
 | 
				
			||||||
// TODO clean up old/unused code, maybe improve comments on whatever is left
 | 
					// TODO clean up old/unused code, maybe improve comments on whatever is left
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Send:
 | 
					// Send:
 | 
				
			||||||
//  Receive a packet from the tun
 | 
					//  Receive a packet from the adapter
 | 
				
			||||||
//  Look up session (if none exists, trigger a search)
 | 
					//  Look up session (if none exists, trigger a search)
 | 
				
			||||||
//  Hand off to session (which encrypts, etc)
 | 
					//  Hand off to session (which encrypts, etc)
 | 
				
			||||||
//  Session will pass it back to router.out, which hands it off to the self peer
 | 
					//  Session will pass it back to router.out, which hands it off to the self peer
 | 
				
			||||||
| 
						 | 
					@ -20,21 +20,18 @@ package yggdrasil
 | 
				
			||||||
//  If it's dht/seach/etc. traffic, the router passes it to that part
 | 
					//  If it's dht/seach/etc. traffic, the router passes it to that part
 | 
				
			||||||
//  If it's an encapsulated IPv6 packet, the router looks up the session for it
 | 
					//  If it's an encapsulated IPv6 packet, the router looks up the session for it
 | 
				
			||||||
//  The packet is passed to the session, which decrypts it, router.recvPacket
 | 
					//  The packet is passed to the session, which decrypts it, router.recvPacket
 | 
				
			||||||
//  The router then runs some sanity checks before passing it to the tun
 | 
					//  The router then runs some sanity checks before passing it to the adapter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"time"
 | 
						"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/address"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
						"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The router struct has channels to/from the tun/tap device and a self peer (0), which is how messages are passed between this node and the peers/switch layer.
 | 
					// The router struct has channels to/from the adapter device and a self peer (0), which is how messages are passed between this node and the peers/switch layer.
 | 
				
			||||||
// The router's mainLoop goroutine is responsible for managing all information related to the dht, searches, and crypto sessions.
 | 
					// The router's mainLoop goroutine is responsible for managing all information related to the dht, searches, and crypto sessions.
 | 
				
			||||||
type router struct {
 | 
					type router struct {
 | 
				
			||||||
	core        *Core
 | 
						core        *Core
 | 
				
			||||||
| 
						 | 
					@ -44,23 +41,44 @@ 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()
 | 
				
			||||||
	tun         tunAdapter             // TUN/TAP adapter
 | 
						adapter     adapterImplementation  // TUN/TAP adapter
 | 
				
			||||||
	adapters    []Adapter              // Other adapters
 | 
						recv        chan<- []byte          // place where the adapter pulls received packets from
 | 
				
			||||||
	recv        chan<- []byte          // place where the tun pulls received packets from
 | 
						send        <-chan []byte          // place where the adapter puts outgoing packets
 | 
				
			||||||
	send        <-chan []byte          // place where the tun puts outgoing packets
 | 
						reject      chan<- RejectedPacket  // place where we send error packets back to adapter
 | 
				
			||||||
	reset       chan struct{}          // signal that coords changed (re-init sessions/dht)
 | 
						reset       chan struct{}          // signal that coords changed (re-init sessions/dht)
 | 
				
			||||||
	admin       chan func()            // pass a lambda for the admin socket to query stuff
 | 
						admin       chan func()            // pass a lambda for the admin socket to query stuff
 | 
				
			||||||
	cryptokey   cryptokey
 | 
						cryptokey   cryptokey
 | 
				
			||||||
	nodeinfo    nodeinfo
 | 
						nodeinfo    nodeinfo
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Packet and session info, used to check that the packet matches a valid IP range or CKR prefix before sending to the tun.
 | 
					// Packet and session info, used to check that the packet matches a valid IP range or CKR prefix before sending to the adapter.
 | 
				
			||||||
type router_recvPacket struct {
 | 
					type router_recvPacket struct {
 | 
				
			||||||
	bs    []byte
 | 
						bs    []byte
 | 
				
			||||||
	sinfo *sessionInfo
 | 
						sinfo *sessionInfo
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Initializes the router struct, which includes setting up channels to/from the tun/tap.
 | 
					// RejectedPacketReason is the type code used to represent the reason that a
 | 
				
			||||||
 | 
					// packet was rejected.
 | 
				
			||||||
 | 
					type RejectedPacketReason int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// The router rejected the packet because it exceeds the session MTU for the
 | 
				
			||||||
 | 
						// given destination. In TUN/TAP, this results in the generation of an ICMPv6
 | 
				
			||||||
 | 
						// Packet Too Big message.
 | 
				
			||||||
 | 
						PacketTooBig = 1 + iota
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RejectedPacket represents a rejected packet from the router. This is passed
 | 
				
			||||||
 | 
					// back to the adapter so that the adapter can respond appropriately, e.g. in
 | 
				
			||||||
 | 
					// the case of TUN/TAP, a "PacketTooBig" reason can be used to generate an
 | 
				
			||||||
 | 
					// ICMPv6 Packet Too Big response.
 | 
				
			||||||
 | 
					type RejectedPacket struct {
 | 
				
			||||||
 | 
						Reason RejectedPacketReason
 | 
				
			||||||
 | 
						Packet []byte
 | 
				
			||||||
 | 
						Detail interface{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Initializes the router struct, which includes setting up channels to/from the adapter.
 | 
				
			||||||
func (r *router) init(core *Core) {
 | 
					func (r *router) init(core *Core) {
 | 
				
			||||||
	r.core = core
 | 
						r.core = core
 | 
				
			||||||
	r.reconfigure = make(chan chan error, 1)
 | 
						r.reconfigure = make(chan chan error, 1)
 | 
				
			||||||
| 
						 | 
					@ -107,16 +125,20 @@ func (r *router) init(core *Core) {
 | 
				
			||||||
	r.toRecv = make(chan router_recvPacket, 32)
 | 
						r.toRecv = make(chan router_recvPacket, 32)
 | 
				
			||||||
	recv := make(chan []byte, 32)
 | 
						recv := make(chan []byte, 32)
 | 
				
			||||||
	send := make(chan []byte, 32)
 | 
						send := make(chan []byte, 32)
 | 
				
			||||||
 | 
						reject := make(chan RejectedPacket, 32)
 | 
				
			||||||
	r.recv = recv
 | 
						r.recv = recv
 | 
				
			||||||
	r.send = send
 | 
						r.send = send
 | 
				
			||||||
 | 
						r.reject = reject
 | 
				
			||||||
	r.reset = make(chan struct{}, 1)
 | 
						r.reset = make(chan struct{}, 1)
 | 
				
			||||||
	r.admin = make(chan func(), 32)
 | 
						r.admin = make(chan func(), 32)
 | 
				
			||||||
	r.nodeinfo.init(r.core)
 | 
						r.nodeinfo.init(r.core)
 | 
				
			||||||
	r.core.configMutex.RLock()
 | 
						r.core.config.Mutex.RLock()
 | 
				
			||||||
	r.nodeinfo.setNodeInfo(r.core.config.NodeInfo, r.core.config.NodeInfoPrivacy)
 | 
						r.nodeinfo.setNodeInfo(r.core.config.Current.NodeInfo, r.core.config.Current.NodeInfoPrivacy)
 | 
				
			||||||
	r.core.configMutex.RUnlock()
 | 
						r.core.config.Mutex.RUnlock()
 | 
				
			||||||
	r.cryptokey.init(r.core)
 | 
						r.cryptokey.init(r.core)
 | 
				
			||||||
	r.tun.init(r.core, send, recv)
 | 
						if r.adapter != nil {
 | 
				
			||||||
 | 
							r.adapter.Init(&r.core.config, r.core.log, send, recv, reject)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Starts the mainLoop goroutine.
 | 
					// Starts the mainLoop goroutine.
 | 
				
			||||||
| 
						 | 
					@ -126,7 +148,7 @@ func (r *router) start() error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Takes traffic from the tun/tap and passes it to router.send, or from r.in and handles incoming traffic.
 | 
					// Takes traffic from the adapter and passes it to router.send, or from r.in and handles incoming traffic.
 | 
				
			||||||
// Also adds new peer info to the DHT.
 | 
					// Also adds new peer info to the DHT.
 | 
				
			||||||
// Also resets the DHT and sesssions in the event of a coord change.
 | 
					// Also resets the DHT and sesssions in the event of a coord change.
 | 
				
			||||||
// Also does periodic maintenance stuff.
 | 
					// Also does periodic maintenance stuff.
 | 
				
			||||||
| 
						 | 
					@ -157,9 +179,8 @@ func (r *router) mainLoop() {
 | 
				
			||||||
		case f := <-r.admin:
 | 
							case f := <-r.admin:
 | 
				
			||||||
			f()
 | 
								f()
 | 
				
			||||||
		case e := <-r.reconfigure:
 | 
							case e := <-r.reconfigure:
 | 
				
			||||||
			r.core.configMutex.RLock()
 | 
								current, _ := r.core.config.Get()
 | 
				
			||||||
			e <- r.nodeinfo.setNodeInfo(r.core.config.NodeInfo, r.core.config.NodeInfoPrivacy)
 | 
								e <- r.nodeinfo.setNodeInfo(current.NodeInfo, current.NodeInfoPrivacy)
 | 
				
			||||||
			r.core.configMutex.RUnlock()
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -168,7 +189,7 @@ func (r *router) mainLoop() {
 | 
				
			||||||
// If a session to the destination exists, gets the session and passes the packet to it.
 | 
					// If a session to the destination exists, gets the session and passes the packet to it.
 | 
				
			||||||
// If no session exists, it triggers (or continues) a search.
 | 
					// If no session exists, it triggers (or continues) a search.
 | 
				
			||||||
// If the session hasn't responded recently, it triggers a ping or search to keep things alive or deal with broken coords *relatively* quickly.
 | 
					// If the session hasn't responded recently, it triggers a ping or search to keep things alive or deal with broken coords *relatively* quickly.
 | 
				
			||||||
// It also deals with oversized packets if there are MTU issues by calling into icmpv6.go to spoof PacketTooBig traffic, or DestinationUnreachable if the other side has their tun/tap disabled.
 | 
					// It also deals with oversized packets if there are MTU issues by calling into icmpv6.go to spoof PacketTooBig traffic, or DestinationUnreachable if the other side has their adapter disabled.
 | 
				
			||||||
func (r *router) sendPacket(bs []byte) {
 | 
					func (r *router) sendPacket(bs []byte) {
 | 
				
			||||||
	var sourceAddr address.Address
 | 
						var sourceAddr address.Address
 | 
				
			||||||
	var destAddr address.Address
 | 
						var destAddr address.Address
 | 
				
			||||||
| 
						 | 
					@ -313,18 +334,11 @@ func (r *router) sendPacket(bs []byte) {
 | 
				
			||||||
				window = int(sinfo.getMTU())
 | 
									window = int(sinfo.getMTU())
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Create the Packet Too Big response
 | 
								// Send the error back to the adapter
 | 
				
			||||||
			ptb := &icmp.PacketTooBig{
 | 
								r.reject <- RejectedPacket{
 | 
				
			||||||
				MTU:  int(sinfo.getMTU()),
 | 
									Reason: PacketTooBig,
 | 
				
			||||||
				Data: bs[:window],
 | 
									Packet: bs[:window],
 | 
				
			||||||
			}
 | 
									Detail: int(sinfo.getMTU()),
 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Create the ICMPv6 response from it
 | 
					 | 
				
			||||||
			icmpv6Buf, err := r.tun.icmpv6.create_icmpv6_tun(
 | 
					 | 
				
			||||||
				bs[8:24], bs[24:40],
 | 
					 | 
				
			||||||
				ipv6.ICMPTypePacketTooBig, 0, ptb)
 | 
					 | 
				
			||||||
			if err == nil {
 | 
					 | 
				
			||||||
				r.recv <- icmpv6Buf
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Don't continue - drop the packet
 | 
								// Don't continue - drop the packet
 | 
				
			||||||
| 
						 | 
					@ -335,7 +349,7 @@ func (r *router) sendPacket(bs []byte) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Called for incoming traffic by the session worker for that connection.
 | 
					// Called for incoming traffic by the session worker for that connection.
 | 
				
			||||||
// Checks that the IP address is correct (matches the session) and passes the packet to the tun/tap.
 | 
					// Checks that the IP address is correct (matches the session) and passes the packet to the adapter.
 | 
				
			||||||
func (r *router) recvPacket(bs []byte, sinfo *sessionInfo) {
 | 
					func (r *router) recvPacket(bs []byte, sinfo *sessionInfo) {
 | 
				
			||||||
	// Note: called directly by the session worker, not the router goroutine
 | 
						// Note: called directly by the session worker, not the router goroutine
 | 
				
			||||||
	if len(bs) < 24 {
 | 
						if len(bs) < 24 {
 | 
				
			||||||
| 
						 | 
					@ -398,7 +412,7 @@ func (r *router) handleIn(packet []byte) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Handles incoming traffic, i.e. encapuslated ordinary IPv6 packets.
 | 
					// Handles incoming traffic, i.e. encapuslated ordinary IPv6 packets.
 | 
				
			||||||
// Passes them to the crypto session worker to be decrypted and sent to the tun/tap.
 | 
					// Passes them to the crypto session worker to be decrypted and sent to the adapter.
 | 
				
			||||||
func (r *router) handleTraffic(packet []byte) {
 | 
					func (r *router) handleTraffic(packet []byte) {
 | 
				
			||||||
	defer util.PutBytes(packet)
 | 
						defer util.PutBytes(packet)
 | 
				
			||||||
	p := wire_trafficPacket{}
 | 
						p := wire_trafficPacket{}
 | 
				
			||||||
| 
						 | 
					@ -432,7 +446,7 @@ func (r *router) handleProto(packet []byte) {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Now do something with the bytes in bs...
 | 
						// Now do something with the bytes in bs...
 | 
				
			||||||
	// send dht messages to dht, sessionRefresh to sessions, data to tun...
 | 
						// send dht messages to dht, sessionRefresh to sessions, data to adapter...
 | 
				
			||||||
	// For data, should check that key and IP match...
 | 
						// For data, should check that key and IP match...
 | 
				
			||||||
	bsType, bsTypeLen := wire_decode_uint64(bs)
 | 
						bsType, bsTypeLen := wire_decode_uint64(bs)
 | 
				
			||||||
	if bsTypeLen == 0 {
 | 
						if bsTypeLen == 0 {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,17 +148,17 @@ func (ss *sessions) init(core *Core) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Determines whether the session firewall is enabled.
 | 
					// Determines whether the session firewall is enabled.
 | 
				
			||||||
func (ss *sessions) isSessionFirewallEnabled() bool {
 | 
					func (ss *sessions) isSessionFirewallEnabled() bool {
 | 
				
			||||||
	ss.core.configMutex.RLock()
 | 
						ss.core.config.Mutex.RLock()
 | 
				
			||||||
	defer ss.core.configMutex.RUnlock()
 | 
						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
 | 
					// Determines whether the session with a given publickey is allowed based on
 | 
				
			||||||
// session firewall rules.
 | 
					// session firewall rules.
 | 
				
			||||||
func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) bool {
 | 
					func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) bool {
 | 
				
			||||||
	ss.core.configMutex.RLock()
 | 
						ss.core.config.Mutex.RLock()
 | 
				
			||||||
	defer ss.core.configMutex.RUnlock()
 | 
						defer ss.core.config.Mutex.RUnlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Allow by default if the session firewall is disabled
 | 
						// Allow by default if the session firewall is disabled
 | 
				
			||||||
	if !ss.isSessionFirewallEnabled() {
 | 
						if !ss.isSessionFirewallEnabled() {
 | 
				
			||||||
| 
						 | 
					@ -167,7 +167,7 @@ func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) b
 | 
				
			||||||
	// Prepare for checking whitelist/blacklist
 | 
						// Prepare for checking whitelist/blacklist
 | 
				
			||||||
	var box crypto.BoxPubKey
 | 
						var box crypto.BoxPubKey
 | 
				
			||||||
	// Reject blacklisted nodes
 | 
						// 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)
 | 
							key, err := hex.DecodeString(b)
 | 
				
			||||||
		if err == nil {
 | 
							if err == nil {
 | 
				
			||||||
			copy(box[:crypto.BoxPubKeyLen], key)
 | 
								copy(box[:crypto.BoxPubKeyLen], key)
 | 
				
			||||||
| 
						 | 
					@ -177,7 +177,7 @@ func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) b
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Allow whitelisted nodes
 | 
						// 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)
 | 
							key, err := hex.DecodeString(b)
 | 
				
			||||||
		if err == nil {
 | 
							if err == nil {
 | 
				
			||||||
			copy(box[:crypto.BoxPubKeyLen], key)
 | 
								copy(box[:crypto.BoxPubKeyLen], key)
 | 
				
			||||||
| 
						 | 
					@ -187,7 +187,7 @@ func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) b
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Allow outbound sessions if appropriate
 | 
						// Allow outbound sessions if appropriate
 | 
				
			||||||
	if ss.core.config.SessionFirewall.AlwaysAllowOutbound {
 | 
						if ss.core.config.Current.SessionFirewall.AlwaysAllowOutbound {
 | 
				
			||||||
		if initiator {
 | 
							if initiator {
 | 
				
			||||||
			return true
 | 
								return true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -201,11 +201,11 @@ func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) b
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Allow direct peers if appropriate
 | 
						// Allow direct peers if appropriate
 | 
				
			||||||
	if ss.core.config.SessionFirewall.AllowFromDirect && isDirectPeer {
 | 
						if ss.core.config.Current.SessionFirewall.AllowFromDirect && isDirectPeer {
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Allow remote nodes if appropriate
 | 
						// Allow remote nodes if appropriate
 | 
				
			||||||
	if ss.core.config.SessionFirewall.AllowFromRemote && !isDirectPeer {
 | 
						if ss.core.config.Current.SessionFirewall.AllowFromRemote && !isDirectPeer {
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Finally, default-deny if not matching any of the above rules
 | 
						// Finally, default-deny if not matching any of the above rules
 | 
				
			||||||
| 
						 | 
					@ -277,7 +277,9 @@ 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
 | 
				
			||||||
	sinfo.myMTU = uint16(ss.core.router.tun.mtu)
 | 
						if ss.core.router.adapter != nil {
 | 
				
			||||||
 | 
							sinfo.myMTU = uint16(ss.core.router.adapter.MTU())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	now := time.Now()
 | 
						now := time.Now()
 | 
				
			||||||
	sinfo.time = now
 | 
						sinfo.time = now
 | 
				
			||||||
	sinfo.mtuTime = now
 | 
						sinfo.mtuTime = now
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -188,9 +188,7 @@ func (t *switchTable) init(core *Core) {
 | 
				
			||||||
	now := time.Now()
 | 
						now := time.Now()
 | 
				
			||||||
	t.core = core
 | 
						t.core = core
 | 
				
			||||||
	t.reconfigure = make(chan chan error, 1)
 | 
						t.reconfigure = make(chan chan error, 1)
 | 
				
			||||||
	t.core.configMutex.RLock()
 | 
					 | 
				
			||||||
	t.key = t.core.sigPub
 | 
						t.key = t.core.sigPub
 | 
				
			||||||
	t.core.configMutex.RUnlock()
 | 
					 | 
				
			||||||
	locator := switchLocator{root: t.key, tstamp: now.Unix()}
 | 
						locator := switchLocator{root: t.key, tstamp: now.Unix()}
 | 
				
			||||||
	peers := make(map[switchPort]peerInfo)
 | 
						peers := make(map[switchPort]peerInfo)
 | 
				
			||||||
	t.data = switchData{locator: locator, peers: peers}
 | 
						t.data = switchData{locator: locator, peers: peers}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,14 +36,18 @@ type tcp struct {
 | 
				
			||||||
	link        *link
 | 
						link        *link
 | 
				
			||||||
	reconfigure chan chan error
 | 
						reconfigure chan chan error
 | 
				
			||||||
	mutex       sync.Mutex // Protecting the below
 | 
						mutex       sync.Mutex // Protecting the below
 | 
				
			||||||
	listeners   map[string]*tcpListener
 | 
						listeners   map[string]*TcpListener
 | 
				
			||||||
	calls       map[string]struct{}
 | 
						calls       map[string]struct{}
 | 
				
			||||||
	conns       map[linkInfo](chan struct{})
 | 
						conns       map[linkInfo](chan struct{})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type tcpListener struct {
 | 
					// TcpListener is a stoppable TCP listener interface. These are typically
 | 
				
			||||||
	listener net.Listener
 | 
					// returned from calls to the ListenTCP() function and are also used internally
 | 
				
			||||||
	stop     chan bool
 | 
					// to represent listeners created by the "Listen" configuration option and for
 | 
				
			||||||
 | 
					// multicast interfaces.
 | 
				
			||||||
 | 
					type TcpListener struct {
 | 
				
			||||||
 | 
						Listener net.Listener
 | 
				
			||||||
 | 
						Stop     chan bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Wrapper function to set additional options for specific connection types.
 | 
					// Wrapper function to set additional options for specific connection types.
 | 
				
			||||||
| 
						 | 
					@ -64,7 +68,7 @@ func (t *tcp) getAddr() *net.TCPAddr {
 | 
				
			||||||
	t.mutex.Lock()
 | 
						t.mutex.Lock()
 | 
				
			||||||
	defer t.mutex.Unlock()
 | 
						defer t.mutex.Unlock()
 | 
				
			||||||
	for _, l := range t.listeners {
 | 
						for _, l := range t.listeners {
 | 
				
			||||||
		return l.listener.Addr().(*net.TCPAddr)
 | 
							return l.Listener.Addr().(*net.TCPAddr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -76,16 +80,16 @@ func (t *tcp) init(l *link) error {
 | 
				
			||||||
	t.mutex.Lock()
 | 
						t.mutex.Lock()
 | 
				
			||||||
	t.calls = make(map[string]struct{})
 | 
						t.calls = make(map[string]struct{})
 | 
				
			||||||
	t.conns = make(map[linkInfo](chan struct{}))
 | 
						t.conns = make(map[linkInfo](chan struct{}))
 | 
				
			||||||
	t.listeners = make(map[string]*tcpListener)
 | 
						t.listeners = make(map[string]*TcpListener)
 | 
				
			||||||
	t.mutex.Unlock()
 | 
						t.mutex.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		for {
 | 
							for {
 | 
				
			||||||
			e := <-t.reconfigure
 | 
								e := <-t.reconfigure
 | 
				
			||||||
			t.link.core.configMutex.RLock()
 | 
								t.link.core.config.Mutex.RLock()
 | 
				
			||||||
			added := util.Difference(t.link.core.config.Listen, t.link.core.configOld.Listen)
 | 
								added := util.Difference(t.link.core.config.Current.Listen, t.link.core.config.Previous.Listen)
 | 
				
			||||||
			deleted := util.Difference(t.link.core.configOld.Listen, t.link.core.config.Listen)
 | 
								deleted := util.Difference(t.link.core.config.Previous.Listen, t.link.core.config.Current.Listen)
 | 
				
			||||||
			t.link.core.configMutex.RUnlock()
 | 
								t.link.core.config.Mutex.RUnlock()
 | 
				
			||||||
			if len(added) > 0 || len(deleted) > 0 {
 | 
								if len(added) > 0 || len(deleted) > 0 {
 | 
				
			||||||
				for _, a := range added {
 | 
									for _, a := range added {
 | 
				
			||||||
					if a[:6] != "tcp://" {
 | 
										if a[:6] != "tcp://" {
 | 
				
			||||||
| 
						 | 
					@ -103,7 +107,7 @@ func (t *tcp) init(l *link) error {
 | 
				
			||||||
					t.mutex.Lock()
 | 
										t.mutex.Lock()
 | 
				
			||||||
					if listener, ok := t.listeners[d[6:]]; ok {
 | 
										if listener, ok := t.listeners[d[6:]]; ok {
 | 
				
			||||||
						t.mutex.Unlock()
 | 
											t.mutex.Unlock()
 | 
				
			||||||
						listener.stop <- true
 | 
											listener.Stop <- true
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						t.mutex.Unlock()
 | 
											t.mutex.Unlock()
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
| 
						 | 
					@ -115,9 +119,9 @@ func (t *tcp) init(l *link) error {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	t.link.core.configMutex.RLock()
 | 
						t.link.core.config.Mutex.RLock()
 | 
				
			||||||
	defer t.link.core.configMutex.RUnlock()
 | 
						defer t.link.core.config.Mutex.RUnlock()
 | 
				
			||||||
	for _, listenaddr := range t.link.core.config.Listen {
 | 
						for _, listenaddr := range t.link.core.config.Current.Listen {
 | 
				
			||||||
		if listenaddr[:6] != "tcp://" {
 | 
							if listenaddr[:6] != "tcp://" {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -129,7 +133,7 @@ func (t *tcp) init(l *link) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (t *tcp) listen(listenaddr string) (*tcpListener, error) {
 | 
					func (t *tcp) listen(listenaddr string) (*TcpListener, error) {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx := context.Background()
 | 
						ctx := context.Background()
 | 
				
			||||||
| 
						 | 
					@ -138,9 +142,9 @@ func (t *tcp) listen(listenaddr string) (*tcpListener, error) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	listener, err := lc.Listen(ctx, "tcp", listenaddr)
 | 
						listener, err := lc.Listen(ctx, "tcp", listenaddr)
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
		l := tcpListener{
 | 
							l := TcpListener{
 | 
				
			||||||
			listener: listener,
 | 
								Listener: listener,
 | 
				
			||||||
			stop:     make(chan bool),
 | 
								Stop:     make(chan bool),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		go t.listener(&l, listenaddr)
 | 
							go t.listener(&l, listenaddr)
 | 
				
			||||||
		return &l, nil
 | 
							return &l, nil
 | 
				
			||||||
| 
						 | 
					@ -150,7 +154,7 @@ func (t *tcp) listen(listenaddr string) (*tcpListener, error) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Runs the listener, which spawns off goroutines for incoming connections.
 | 
					// Runs the listener, which spawns off goroutines for incoming connections.
 | 
				
			||||||
func (t *tcp) listener(l *tcpListener, listenaddr string) {
 | 
					func (t *tcp) listener(l *TcpListener, listenaddr string) {
 | 
				
			||||||
	if l == nil {
 | 
						if l == nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -158,7 +162,7 @@ func (t *tcp) listener(l *tcpListener, listenaddr string) {
 | 
				
			||||||
	t.mutex.Lock()
 | 
						t.mutex.Lock()
 | 
				
			||||||
	if _, isIn := t.listeners[listenaddr]; isIn {
 | 
						if _, isIn := t.listeners[listenaddr]; isIn {
 | 
				
			||||||
		t.mutex.Unlock()
 | 
							t.mutex.Unlock()
 | 
				
			||||||
		l.listener.Close()
 | 
							l.Listener.Close()
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		t.listeners[listenaddr] = l
 | 
							t.listeners[listenaddr] = l
 | 
				
			||||||
| 
						 | 
					@ -167,20 +171,20 @@ func (t *tcp) listener(l *tcpListener, listenaddr string) {
 | 
				
			||||||
	// And here we go!
 | 
						// And here we go!
 | 
				
			||||||
	accepted := make(chan bool)
 | 
						accepted := make(chan bool)
 | 
				
			||||||
	defer func() {
 | 
						defer func() {
 | 
				
			||||||
		t.link.core.log.Infoln("Stopping TCP listener on:", l.listener.Addr().String())
 | 
							t.link.core.log.Infoln("Stopping TCP listener on:", l.Listener.Addr().String())
 | 
				
			||||||
		l.listener.Close()
 | 
							l.Listener.Close()
 | 
				
			||||||
		t.mutex.Lock()
 | 
							t.mutex.Lock()
 | 
				
			||||||
		delete(t.listeners, listenaddr)
 | 
							delete(t.listeners, listenaddr)
 | 
				
			||||||
		t.mutex.Unlock()
 | 
							t.mutex.Unlock()
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
	t.link.core.log.Infoln("Listening for TCP on:", l.listener.Addr().String())
 | 
						t.link.core.log.Infoln("Listening for TCP on:", l.Listener.Addr().String())
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		var sock net.Conn
 | 
							var sock net.Conn
 | 
				
			||||||
		var err error
 | 
							var err error
 | 
				
			||||||
		// Listen in a separate goroutine, as that way it does not block us from
 | 
							// Listen in a separate goroutine, as that way it does not block us from
 | 
				
			||||||
		// receiving "stop" events
 | 
							// receiving "stop" events
 | 
				
			||||||
		go func() {
 | 
							go func() {
 | 
				
			||||||
			sock, err = l.listener.Accept()
 | 
								sock, err = l.Listener.Accept()
 | 
				
			||||||
			accepted <- true
 | 
								accepted <- true
 | 
				
			||||||
		}()
 | 
							}()
 | 
				
			||||||
		// Wait for either an accepted connection, or a message telling us to stop
 | 
							// Wait for either an accepted connection, or a message telling us to stop
 | 
				
			||||||
| 
						 | 
					@ -192,7 +196,7 @@ func (t *tcp) listener(l *tcpListener, listenaddr string) {
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			go t.handler(sock, true, nil)
 | 
								go t.handler(sock, true, nil)
 | 
				
			||||||
		case <-l.stop:
 | 
							case <-l.Stop:
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,266 +0,0 @@
 | 
				
			||||||
package yggdrasil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This manages the tun driver to send/recv packets to/from applications
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"net"
 | 
					 | 
				
			||||||
	"sync"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"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/defaults"
 | 
					 | 
				
			||||||
	"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const tun_IPv6_HEADER_LENGTH = 40
 | 
					 | 
				
			||||||
const tun_ETHER_HEADER_LENGTH = 14
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Represents a running TUN/TAP interface.
 | 
					 | 
				
			||||||
type tunAdapter struct {
 | 
					 | 
				
			||||||
	Adapter
 | 
					 | 
				
			||||||
	icmpv6 icmpv6
 | 
					 | 
				
			||||||
	mtu    int
 | 
					 | 
				
			||||||
	iface  *water.Interface
 | 
					 | 
				
			||||||
	mutex  sync.RWMutex // Protects the below
 | 
					 | 
				
			||||||
	isOpen bool
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Gets the maximum supported MTU for the platform based on the defaults in
 | 
					 | 
				
			||||||
// defaults.GetDefaults().
 | 
					 | 
				
			||||||
func getSupportedMTU(mtu int) int {
 | 
					 | 
				
			||||||
	if mtu > defaults.GetDefaults().MaximumIfMTU {
 | 
					 | 
				
			||||||
		return defaults.GetDefaults().MaximumIfMTU
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return mtu
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 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)
 | 
					 | 
				
			||||||
	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()
 | 
					 | 
				
			||||||
			if updated {
 | 
					 | 
				
			||||||
				tun.core.log.Warnln("Reconfiguring TUN/TAP is not supported yet")
 | 
					 | 
				
			||||||
				e <- nil
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				e <- nil
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 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()
 | 
					 | 
				
			||||||
	if ifname != "none" {
 | 
					 | 
				
			||||||
		if err := tun.setup(ifname, iftapmode, addr, mtu); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if ifname == "none" || ifname == "dummy" {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	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()) }()
 | 
					 | 
				
			||||||
	if iftapmode {
 | 
					 | 
				
			||||||
		go func() {
 | 
					 | 
				
			||||||
			for {
 | 
					 | 
				
			||||||
				if _, ok := tun.icmpv6.peermacs[tun.core.router.addr]; ok {
 | 
					 | 
				
			||||||
					break
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				request, err := tun.icmpv6.create_ndp_tap(tun.core.router.addr)
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					panic(err)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if _, err := tun.iface.Write(request); err != nil {
 | 
					 | 
				
			||||||
					panic(err)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				time.Sleep(time.Second)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 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 {
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		data := <-tun.recv
 | 
					 | 
				
			||||||
		if tun.iface == nil {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if tun.iface.IsTAP() {
 | 
					 | 
				
			||||||
			var destAddr address.Address
 | 
					 | 
				
			||||||
			if data[0]&0xf0 == 0x60 {
 | 
					 | 
				
			||||||
				if len(data) < 40 {
 | 
					 | 
				
			||||||
					panic("Tried to send a packet shorter than an IPv6 header...")
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				copy(destAddr[:16], data[24:])
 | 
					 | 
				
			||||||
			} else if data[0]&0xf0 == 0x40 {
 | 
					 | 
				
			||||||
				if len(data) < 20 {
 | 
					 | 
				
			||||||
					panic("Tried to send a packet shorter than an IPv4 header...")
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				copy(destAddr[:4], data[16:])
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				return errors.New("Invalid address family")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			sendndp := func(destAddr address.Address) {
 | 
					 | 
				
			||||||
				neigh, known := tun.icmpv6.peermacs[destAddr]
 | 
					 | 
				
			||||||
				known = known && (time.Since(neigh.lastsolicitation).Seconds() < 30)
 | 
					 | 
				
			||||||
				if !known {
 | 
					 | 
				
			||||||
					request, err := tun.icmpv6.create_ndp_tap(destAddr)
 | 
					 | 
				
			||||||
					if err != nil {
 | 
					 | 
				
			||||||
						panic(err)
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					if _, err := tun.iface.Write(request); err != nil {
 | 
					 | 
				
			||||||
						panic(err)
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					tun.icmpv6.peermacs[destAddr] = neighbor{
 | 
					 | 
				
			||||||
						lastsolicitation: time.Now(),
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			var peermac macAddress
 | 
					 | 
				
			||||||
			var peerknown bool
 | 
					 | 
				
			||||||
			if data[0]&0xf0 == 0x40 {
 | 
					 | 
				
			||||||
				destAddr = tun.core.router.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 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 {
 | 
					 | 
				
			||||||
				peermac = neighbor.mac
 | 
					 | 
				
			||||||
				peerknown = true
 | 
					 | 
				
			||||||
				sendndp(destAddr)
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				sendndp(tun.core.router.addr)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if peerknown {
 | 
					 | 
				
			||||||
				var proto ethernet.Ethertype
 | 
					 | 
				
			||||||
				switch {
 | 
					 | 
				
			||||||
				case data[0]&0xf0 == 0x60:
 | 
					 | 
				
			||||||
					proto = ethernet.IPv6
 | 
					 | 
				
			||||||
				case data[0]&0xf0 == 0x40:
 | 
					 | 
				
			||||||
					proto = ethernet.IPv4
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				var frame ethernet.Frame
 | 
					 | 
				
			||||||
				frame.Prepare(
 | 
					 | 
				
			||||||
					peermac[:6],          // Destination MAC address
 | 
					 | 
				
			||||||
					tun.icmpv6.mymac[:6], // Source MAC address
 | 
					 | 
				
			||||||
					ethernet.NotTagged,   // VLAN tagging
 | 
					 | 
				
			||||||
					proto,                // Ethertype
 | 
					 | 
				
			||||||
					len(data))            // Payload length
 | 
					 | 
				
			||||||
				copy(frame[tun_ETHER_HEADER_LENGTH:], data[:])
 | 
					 | 
				
			||||||
				if _, err := tun.iface.Write(frame); err != nil {
 | 
					 | 
				
			||||||
					tun.mutex.RLock()
 | 
					 | 
				
			||||||
					open := tun.isOpen
 | 
					 | 
				
			||||||
					tun.mutex.RUnlock()
 | 
					 | 
				
			||||||
					if !open {
 | 
					 | 
				
			||||||
						return nil
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						panic(err)
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			if _, err := tun.iface.Write(data); err != nil {
 | 
					 | 
				
			||||||
				tun.mutex.RLock()
 | 
					 | 
				
			||||||
				open := tun.isOpen
 | 
					 | 
				
			||||||
				tun.mutex.RUnlock()
 | 
					 | 
				
			||||||
				if !open {
 | 
					 | 
				
			||||||
					return nil
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					panic(err)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		util.PutBytes(data)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Reads any packets that are waiting on the TUN/TAP adapter. If the adapter
 | 
					 | 
				
			||||||
// 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 {
 | 
					 | 
				
			||||||
	mtu := tun.mtu
 | 
					 | 
				
			||||||
	if tun.iface.IsTAP() {
 | 
					 | 
				
			||||||
		mtu += tun_ETHER_HEADER_LENGTH
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	buf := make([]byte, mtu)
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		n, err := tun.iface.Read(buf)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			tun.mutex.RLock()
 | 
					 | 
				
			||||||
			open := tun.isOpen
 | 
					 | 
				
			||||||
			tun.mutex.RUnlock()
 | 
					 | 
				
			||||||
			if !open {
 | 
					 | 
				
			||||||
				return nil
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				// panic(err)
 | 
					 | 
				
			||||||
				return err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		o := 0
 | 
					 | 
				
			||||||
		if tun.iface.IsTAP() {
 | 
					 | 
				
			||||||
			o = tun_ETHER_HEADER_LENGTH
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		switch {
 | 
					 | 
				
			||||||
		case buf[o]&0xf0 == 0x60 && n == 256*int(buf[o+4])+int(buf[o+5])+tun_IPv6_HEADER_LENGTH+o:
 | 
					 | 
				
			||||||
		case buf[o]&0xf0 == 0x40 && n == 256*int(buf[o+2])+int(buf[o+3])+o:
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if buf[o+6] == 58 {
 | 
					 | 
				
			||||||
			if tun.iface.IsTAP() {
 | 
					 | 
				
			||||||
				// Found an ICMPv6 packet
 | 
					 | 
				
			||||||
				b := make([]byte, n)
 | 
					 | 
				
			||||||
				copy(b, buf)
 | 
					 | 
				
			||||||
				go tun.icmpv6.parse_packet(b)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		packet := append(util.GetBytes(), buf[o:n]...)
 | 
					 | 
				
			||||||
		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 {
 | 
					 | 
				
			||||||
	tun.mutex.Lock()
 | 
					 | 
				
			||||||
	tun.isOpen = false
 | 
					 | 
				
			||||||
	tun.mutex.Unlock()
 | 
					 | 
				
			||||||
	if tun.iface == nil {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return tun.iface.Close()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue