mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 03:05:07 +03:00 
			
		
		
		
	Drop Water, use Wireguard tun library, drop TAP support
This commit is contained in:
		
							parent
							
								
									07ce8cde7a
								
							
						
					
					
						commit
						f5517acc81
					
				
					 20 changed files with 146 additions and 616 deletions
				
			
		| 
						 | 
				
			
			@ -71,7 +71,6 @@ type NodeConfig struct {
 | 
			
		|||
	SigningPrivateKey           string                 `comment:"Your private signing key. DO NOT share this with anyone!"`
 | 
			
		||||
	LinkLocalTCPPort            uint16                 `comment:"The port number to be used for the link-local TCP listeners for the\nconfigured MulticastInterfaces. This option does not affect listeners\nspecified in the Listen option. Unless you plan to firewall link-local\ntraffic, it is best to leave this as the default value of 0. This\noption cannot currently be changed by reloading config during runtime."`
 | 
			
		||||
	IfName                      string                 `comment:"Local network interface name for TUN/TAP adapter, or \"auto\" to select\nan interface automatically, or \"none\" to run without TUN/TAP."`
 | 
			
		||||
	IfTAPMode                   bool                   `comment:"Set local network interface to TAP mode rather than TUN mode if\nsupported by your platform - option will be ignored if not."`
 | 
			
		||||
	IfMTU                       int                    `comment:"Maximux Transmission Unit (MTU) size for your local TUN/TAP interface.\nDefault is the largest supported size for your platform. The lowest\npossible value is 1280."`
 | 
			
		||||
	SessionFirewall             SessionFirewall        `comment:"The session firewall controls who can send/receive network traffic\nto/from. This is useful if you want to protect this node without\nresorting to using a real firewall. This does not affect traffic\nbeing routed via this node to somewhere else. Rules are prioritised as\nfollows: blacklist, whitelist, always allow outgoing, direct, remote."`
 | 
			
		||||
	TunnelRouting               TunnelRouting          `comment:"Allow tunneling non-Yggdrasil traffic over Yggdrasil. This effectively\nallows you to use Yggdrasil to route to, or to bridge other networks,\nsimilar to a VPN tunnel. Tunnelling works between any two nodes and\ndoes not require them to be directly peered."`
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +126,6 @@ func GenerateConfig() *NodeConfig {
 | 
			
		|||
	cfg.MulticastInterfaces = defaults.GetDefaults().DefaultMulticastInterfaces
 | 
			
		||||
	cfg.IfName = defaults.GetDefaults().DefaultIfName
 | 
			
		||||
	cfg.IfMTU = defaults.GetDefaults().DefaultIfMTU
 | 
			
		||||
	cfg.IfTAPMode = defaults.GetDefaults().DefaultIfTAPMode
 | 
			
		||||
	cfg.SessionFirewall.Enable = false
 | 
			
		||||
	cfg.SessionFirewall.AllowFromDirect = true
 | 
			
		||||
	cfg.SessionFirewall.AllowFromRemote = true
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,8 +14,7 @@ type platformDefaultParameters struct {
 | 
			
		|||
	DefaultMulticastInterfaces []string
 | 
			
		||||
 | 
			
		||||
	// TUN/TAP
 | 
			
		||||
	MaximumIfMTU     int
 | 
			
		||||
	DefaultIfMTU     int
 | 
			
		||||
	DefaultIfName    string
 | 
			
		||||
	DefaultIfTAPMode bool
 | 
			
		||||
	MaximumIfMTU  int
 | 
			
		||||
	DefaultIfMTU  int
 | 
			
		||||
	DefaultIfName string
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,9 +19,8 @@ func GetDefaults() platformDefaultParameters {
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		// TUN/TAP
 | 
			
		||||
		MaximumIfMTU:     65535,
 | 
			
		||||
		DefaultIfMTU:     65535,
 | 
			
		||||
		DefaultIfName:    "auto",
 | 
			
		||||
		DefaultIfTAPMode: false,
 | 
			
		||||
		MaximumIfMTU:  65535,
 | 
			
		||||
		DefaultIfMTU:  65535,
 | 
			
		||||
		DefaultIfName: "auto",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,9 +18,8 @@ func GetDefaults() platformDefaultParameters {
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		// TUN/TAP
 | 
			
		||||
		MaximumIfMTU:     32767,
 | 
			
		||||
		DefaultIfMTU:     32767,
 | 
			
		||||
		DefaultIfName:    "/dev/tap0",
 | 
			
		||||
		DefaultIfTAPMode: true,
 | 
			
		||||
		MaximumIfMTU:  32767,
 | 
			
		||||
		DefaultIfMTU:  32767,
 | 
			
		||||
		DefaultIfName: "/dev/tap0",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,9 +18,8 @@ func GetDefaults() platformDefaultParameters {
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		// TUN/TAP
 | 
			
		||||
		MaximumIfMTU:     65535,
 | 
			
		||||
		DefaultIfMTU:     65535,
 | 
			
		||||
		DefaultIfName:    "auto",
 | 
			
		||||
		DefaultIfTAPMode: false,
 | 
			
		||||
		MaximumIfMTU:  65535,
 | 
			
		||||
		DefaultIfMTU:  65535,
 | 
			
		||||
		DefaultIfName: "auto",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,9 +18,8 @@ func GetDefaults() platformDefaultParameters {
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		// TUN/TAP
 | 
			
		||||
		MaximumIfMTU:     9000,
 | 
			
		||||
		DefaultIfMTU:     9000,
 | 
			
		||||
		DefaultIfName:    "/dev/tap0",
 | 
			
		||||
		DefaultIfTAPMode: true,
 | 
			
		||||
		MaximumIfMTU:  9000,
 | 
			
		||||
		DefaultIfMTU:  9000,
 | 
			
		||||
		DefaultIfName: "/dev/tun0",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,9 +18,8 @@ func GetDefaults() platformDefaultParameters {
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		// TUN/TAP
 | 
			
		||||
		MaximumIfMTU:     16384,
 | 
			
		||||
		DefaultIfMTU:     16384,
 | 
			
		||||
		DefaultIfName:    "/dev/tap0",
 | 
			
		||||
		DefaultIfTAPMode: true,
 | 
			
		||||
		MaximumIfMTU:  16384,
 | 
			
		||||
		DefaultIfMTU:  16384,
 | 
			
		||||
		DefaultIfName: "/dev/tun0",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,9 +18,8 @@ func GetDefaults() platformDefaultParameters {
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		// TUN/TAP
 | 
			
		||||
		MaximumIfMTU:     65535,
 | 
			
		||||
		DefaultIfMTU:     65535,
 | 
			
		||||
		DefaultIfName:    "none",
 | 
			
		||||
		DefaultIfTAPMode: false,
 | 
			
		||||
		MaximumIfMTU:  65535,
 | 
			
		||||
		DefaultIfMTU:  65535,
 | 
			
		||||
		DefaultIfName: "none",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,9 +18,8 @@ func GetDefaults() platformDefaultParameters {
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		// TUN/TAP
 | 
			
		||||
		MaximumIfMTU:     65535,
 | 
			
		||||
		DefaultIfMTU:     65535,
 | 
			
		||||
		DefaultIfName:    "auto",
 | 
			
		||||
		DefaultIfTAPMode: true,
 | 
			
		||||
		MaximumIfMTU:  65535,
 | 
			
		||||
		DefaultIfMTU:  65535,
 | 
			
		||||
		DefaultIfName: "auto",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,9 +19,8 @@ func (t *TunAdapter) SetupAdminHandlers(a *admin.AdminSocket) {
 | 
			
		|||
		}()
 | 
			
		||||
 | 
			
		||||
		return admin.Info{
 | 
			
		||||
			t.iface.Name(): admin.Info{
 | 
			
		||||
				"tap_mode": t.iface.IsTAP(),
 | 
			
		||||
				"mtu":      t.mtu,
 | 
			
		||||
			t.Name(): admin.Info{
 | 
			
		||||
				"mtu": t.mtu,
 | 
			
		||||
			},
 | 
			
		||||
		}, nil
 | 
			
		||||
	})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,32 +11,16 @@ package tuntap
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"net"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/net/icmp"
 | 
			
		||||
	"golang.org/x/net/ipv6"
 | 
			
		||||
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const len_ETHER = 14
 | 
			
		||||
 | 
			
		||||
type ICMPv6 struct {
 | 
			
		||||
	tun           *TunAdapter
 | 
			
		||||
	mylladdr      net.IP
 | 
			
		||||
	mymac         net.HardwareAddr
 | 
			
		||||
	peermacs      map[address.Address]neighbor
 | 
			
		||||
	peermacsmutex sync.RWMutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type neighbor struct {
 | 
			
		||||
	mac               net.HardwareAddr
 | 
			
		||||
	learned           bool
 | 
			
		||||
	lastadvertisement time.Time
 | 
			
		||||
	lastsolicitation  time.Time
 | 
			
		||||
	tun *TunAdapter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Marshal returns the binary encoding of h.
 | 
			
		||||
| 
						 | 
				
			
			@ -61,182 +45,6 @@ func ipv6Header_Marshal(h *ipv6.Header) ([]byte, error) {
 | 
			
		|||
// addresses.
 | 
			
		||||
func (i *ICMPv6) Init(t *TunAdapter) {
 | 
			
		||||
	i.tun = t
 | 
			
		||||
	i.peermacsmutex.Lock()
 | 
			
		||||
	i.peermacs = make(map[address.Address]neighbor)
 | 
			
		||||
	i.peermacsmutex.Unlock()
 | 
			
		||||
 | 
			
		||||
	// Our MAC address and link-local address
 | 
			
		||||
	i.mymac = net.HardwareAddr{
 | 
			
		||||
		0x02, 0x00, 0x00, 0x00, 0x00, 0x02}
 | 
			
		||||
	i.mylladdr = net.IP{
 | 
			
		||||
		0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFE}
 | 
			
		||||
	copy(i.mymac[:], i.tun.addr[:])
 | 
			
		||||
	copy(i.mylladdr[9:], i.tun.addr[1:])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parses an incoming ICMPv6 packet. The packet provided may be either an
 | 
			
		||||
// ethernet frame containing an IP packet, or the IP packet alone. This is
 | 
			
		||||
// determined by whether the TUN/TAP adapter is running in TUN (layer 3) or
 | 
			
		||||
// TAP (layer 2) mode. Returns an error condition which is nil if the ICMPv6
 | 
			
		||||
// module handled the packet or contains the error if not.
 | 
			
		||||
func (i *ICMPv6) ParsePacket(datain []byte) error {
 | 
			
		||||
	var response []byte
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	// Parse the frame/packet
 | 
			
		||||
	if i.tun.IsTAP() {
 | 
			
		||||
		response, err = i.UnmarshalPacketL2(datain)
 | 
			
		||||
	} else {
 | 
			
		||||
		response, err = i.UnmarshalPacket(datain, nil)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Write the packet to TUN/TAP
 | 
			
		||||
	i.tun.iface.Write(response)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unwraps the ethernet headers of an incoming ICMPv6 packet and hands off
 | 
			
		||||
// the IP packet to the ParsePacket function for further processing.
 | 
			
		||||
// A response buffer is also created for the response message, also complete
 | 
			
		||||
// with ethernet headers.
 | 
			
		||||
func (i *ICMPv6) UnmarshalPacketL2(datain []byte) ([]byte, error) {
 | 
			
		||||
	// Ignore non-IPv6 frames
 | 
			
		||||
	if binary.BigEndian.Uint16(datain[12:14]) != uint16(0x86DD) {
 | 
			
		||||
		return nil, errors.New("Ignoring non-IPv6 frame")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Hand over to ParsePacket to interpret the IPv6 packet
 | 
			
		||||
	mac := datain[6:12]
 | 
			
		||||
	ipv6packet, err := i.UnmarshalPacket(datain[len_ETHER:], &mac)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create the response buffer
 | 
			
		||||
	dataout := make([]byte, len_ETHER+ipv6.HeaderLen+32)
 | 
			
		||||
 | 
			
		||||
	// Populate the response ethernet headers
 | 
			
		||||
	copy(dataout[:6], datain[6:12])
 | 
			
		||||
	copy(dataout[6:12], i.mymac[:])
 | 
			
		||||
	binary.BigEndian.PutUint16(dataout[12:14], uint16(0x86DD))
 | 
			
		||||
 | 
			
		||||
	// Copy the returned packet to our response ethernet frame
 | 
			
		||||
	copy(dataout[len_ETHER:], ipv6packet)
 | 
			
		||||
	return dataout, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unwraps the IP headers of an incoming IPv6 packet and performs various
 | 
			
		||||
// sanity checks on the packet - i.e. is the packet an ICMPv6 packet, does the
 | 
			
		||||
// ICMPv6 message match a known expected type. The relevant handler function
 | 
			
		||||
// is then called and a response packet may be returned.
 | 
			
		||||
func (i *ICMPv6) UnmarshalPacket(datain []byte, datamac *[]byte) ([]byte, error) {
 | 
			
		||||
	// Parse the IPv6 packet headers
 | 
			
		||||
	ipv6Header, err := ipv6.ParseHeader(datain[:ipv6.HeaderLen])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check if the packet is IPv6
 | 
			
		||||
	if ipv6Header.Version != ipv6.Version {
 | 
			
		||||
		return nil, errors.New("Ignoring non-IPv6 packet")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check if the packet is ICMPv6
 | 
			
		||||
	if ipv6Header.NextHeader != 58 {
 | 
			
		||||
		return nil, errors.New("Ignoring non-ICMPv6 packet")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Parse the ICMPv6 message contents
 | 
			
		||||
	icmpv6Header, err := icmp.ParseMessage(58, datain[ipv6.HeaderLen:])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check for a supported message type
 | 
			
		||||
	switch icmpv6Header.Type {
 | 
			
		||||
	case ipv6.ICMPTypeNeighborSolicitation:
 | 
			
		||||
		if !i.tun.IsTAP() {
 | 
			
		||||
			return nil, errors.New("Ignoring Neighbor Solicitation in TUN mode")
 | 
			
		||||
		}
 | 
			
		||||
		response, err := i.HandleNDP(datain[ipv6.HeaderLen:])
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			// Create our ICMPv6 response
 | 
			
		||||
			responsePacket, err := CreateICMPv6(
 | 
			
		||||
				ipv6Header.Src, i.mylladdr,
 | 
			
		||||
				ipv6.ICMPTypeNeighborAdvertisement, 0,
 | 
			
		||||
				&icmp.DefaultMessageBody{Data: response})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			// Send it back
 | 
			
		||||
			return responsePacket, nil
 | 
			
		||||
		} else {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	case ipv6.ICMPTypeNeighborAdvertisement:
 | 
			
		||||
		if !i.tun.IsTAP() {
 | 
			
		||||
			return nil, errors.New("Ignoring Neighbor Advertisement in TUN mode")
 | 
			
		||||
		}
 | 
			
		||||
		if datamac != nil {
 | 
			
		||||
			var addr address.Address
 | 
			
		||||
			var target address.Address
 | 
			
		||||
			mac := net.HardwareAddr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 | 
			
		||||
			copy(addr[:], ipv6Header.Src[:])
 | 
			
		||||
			copy(target[:], datain[48:64])
 | 
			
		||||
			copy(mac[:], (*datamac)[:])
 | 
			
		||||
			i.peermacsmutex.Lock()
 | 
			
		||||
			neighbor := i.peermacs[target]
 | 
			
		||||
			neighbor.mac = mac
 | 
			
		||||
			neighbor.learned = true
 | 
			
		||||
			neighbor.lastadvertisement = time.Now()
 | 
			
		||||
			i.peermacs[target] = neighbor
 | 
			
		||||
			i.peermacsmutex.Unlock()
 | 
			
		||||
			i.tun.log.Debugln("Learned peer MAC", mac.String(), "for", net.IP(target[:]).String())
 | 
			
		||||
			/*
 | 
			
		||||
				i.tun.log.Debugln("Peer MAC table:")
 | 
			
		||||
				i.peermacsmutex.RLock()
 | 
			
		||||
				for t, n := range i.peermacs {
 | 
			
		||||
					if n.learned {
 | 
			
		||||
						i.tun.log.Debugln("- Target", net.IP(t[:]).String(), "has MAC", n.mac.String())
 | 
			
		||||
					} else {
 | 
			
		||||
						i.tun.log.Debugln("- Target", net.IP(t[:]).String(), "is not learned yet")
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				i.peermacsmutex.RUnlock()
 | 
			
		||||
			*/
 | 
			
		||||
		}
 | 
			
		||||
		return nil, errors.New("No response needed")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, errors.New("ICMPv6 type not matched")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Creates an ICMPv6 packet based on the given icmp.MessageBody and other
 | 
			
		||||
// parameters, complete with ethernet and IP headers, which can be written
 | 
			
		||||
// directly to a TAP adapter.
 | 
			
		||||
func (i *ICMPv6) CreateICMPv6L2(dstmac net.HardwareAddr, dst net.IP, src net.IP, mtype ipv6.ICMPType, mcode int, mbody icmp.MessageBody) ([]byte, error) {
 | 
			
		||||
	// Pass through to CreateICMPv6
 | 
			
		||||
	ipv6packet, err := CreateICMPv6(dst, src, mtype, mcode, mbody)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create the response buffer
 | 
			
		||||
	dataout := make([]byte, len_ETHER+len(ipv6packet))
 | 
			
		||||
 | 
			
		||||
	// Populate the response ethernet headers
 | 
			
		||||
	copy(dataout[:6], dstmac[:6])
 | 
			
		||||
	copy(dataout[6:12], i.mymac[:])
 | 
			
		||||
	binary.BigEndian.PutUint16(dataout[12:14], uint16(0x86DD))
 | 
			
		||||
 | 
			
		||||
	// Copy the returned packet to our response ethernet frame
 | 
			
		||||
	copy(dataout[len_ETHER:], ipv6packet)
 | 
			
		||||
	return dataout, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Creates an ICMPv6 packet based on the given icmp.MessageBody and other
 | 
			
		||||
| 
						 | 
				
			
			@ -281,106 +89,3 @@ func CreateICMPv6(dst net.IP, src net.IP, mtype ipv6.ICMPType, mcode int, mbody
 | 
			
		|||
	// Send it back
 | 
			
		||||
	return responsePacket, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *ICMPv6) Solicit(addr address.Address) {
 | 
			
		||||
	retries := 5
 | 
			
		||||
	for retries > 0 {
 | 
			
		||||
		retries--
 | 
			
		||||
		i.peermacsmutex.RLock()
 | 
			
		||||
		if n, ok := i.peermacs[addr]; ok && n.learned {
 | 
			
		||||
			i.tun.log.Debugln("MAC learned for", net.IP(addr[:]).String())
 | 
			
		||||
			i.peermacsmutex.RUnlock()
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		i.peermacsmutex.RUnlock()
 | 
			
		||||
		i.tun.log.Debugln("Sending neighbor solicitation for", net.IP(addr[:]).String())
 | 
			
		||||
		i.peermacsmutex.Lock()
 | 
			
		||||
		if n, ok := i.peermacs[addr]; !ok {
 | 
			
		||||
			i.peermacs[addr] = neighbor{
 | 
			
		||||
				lastsolicitation: time.Now(),
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			n.lastsolicitation = time.Now()
 | 
			
		||||
		}
 | 
			
		||||
		i.peermacsmutex.Unlock()
 | 
			
		||||
		request, err := i.createNDPL2(addr)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
		if _, err := i.tun.iface.Write(request); err != nil {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
		i.tun.log.Debugln("Sent neighbor solicitation for", net.IP(addr[:]).String())
 | 
			
		||||
		time.Sleep(time.Second)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *ICMPv6) getNeighbor(addr address.Address) (neighbor, bool) {
 | 
			
		||||
	i.peermacsmutex.RLock()
 | 
			
		||||
	defer i.peermacsmutex.RUnlock()
 | 
			
		||||
 | 
			
		||||
	n, ok := i.peermacs[addr]
 | 
			
		||||
	return n, ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *ICMPv6) createNDPL2(dst address.Address) ([]byte, error) {
 | 
			
		||||
	// Create the ND payload
 | 
			
		||||
	var payload [28]byte
 | 
			
		||||
	copy(payload[:4], []byte{0x00, 0x00, 0x00, 0x00}) // Flags
 | 
			
		||||
	copy(payload[4:20], dst[:])                       // Destination
 | 
			
		||||
	copy(payload[20:22], []byte{0x01, 0x01})          // Type & length
 | 
			
		||||
	copy(payload[22:28], i.mymac[:6])                 // Link layer address
 | 
			
		||||
 | 
			
		||||
	// Create the ICMPv6 solicited-node address
 | 
			
		||||
	var dstaddr address.Address
 | 
			
		||||
	copy(dstaddr[:13], []byte{
 | 
			
		||||
		0xFF, 0x02, 0x00, 0x00,
 | 
			
		||||
		0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
		0x00, 0x00, 0x00, 0x01, 0xFF})
 | 
			
		||||
	copy(dstaddr[13:], dst[13:16])
 | 
			
		||||
 | 
			
		||||
	// Create the multicast MAC
 | 
			
		||||
	dstmac := net.HardwareAddr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 | 
			
		||||
	copy(dstmac[:2], []byte{0x33, 0x33})
 | 
			
		||||
	copy(dstmac[2:6], dstaddr[12:16])
 | 
			
		||||
 | 
			
		||||
	// Create the ND request
 | 
			
		||||
	requestPacket, err := i.CreateICMPv6L2(
 | 
			
		||||
		dstmac, dstaddr[:], i.mylladdr,
 | 
			
		||||
		ipv6.ICMPTypeNeighborSolicitation, 0,
 | 
			
		||||
		&icmp.DefaultMessageBody{Data: payload[:]})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return requestPacket, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Generates a response to an NDP discovery packet. This is effectively called
 | 
			
		||||
// when the host operating system generates an NDP request for any address in
 | 
			
		||||
// the fd00::/8 range, so that the operating system knows to route that traffic
 | 
			
		||||
// to the Yggdrasil TAP adapter.
 | 
			
		||||
func (i *ICMPv6) HandleNDP(in []byte) ([]byte, error) {
 | 
			
		||||
	// Ignore NDP requests for anything outside of fd00::/8
 | 
			
		||||
	var source address.Address
 | 
			
		||||
	copy(source[:], in[8:])
 | 
			
		||||
	var snet address.Subnet
 | 
			
		||||
	copy(snet[:], in[8:])
 | 
			
		||||
	switch {
 | 
			
		||||
	case source.IsValid():
 | 
			
		||||
	case snet.IsValid():
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, errors.New("Not an NDP for 0200::/7")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create our NDP message body response
 | 
			
		||||
	body := make([]byte, 28)
 | 
			
		||||
	binary.BigEndian.PutUint32(body[:4], uint32(0x40000000)) // Flags
 | 
			
		||||
	copy(body[4:20], in[8:24])                               // Target address
 | 
			
		||||
	body[20] = uint8(2)                                      // Type: Target link-layer address
 | 
			
		||||
	body[21] = uint8(1)                                      // Length: 1x address (8 bytes)
 | 
			
		||||
	copy(body[22:28], i.mymac[:6])
 | 
			
		||||
 | 
			
		||||
	// Send it back
 | 
			
		||||
	return body, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,6 @@
 | 
			
		|||
package tuntap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"net"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/songgao/packets/ethernet"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +9,8 @@ import (
 | 
			
		|||
	"github.com/Arceliar/phony"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const TUN_OFFSET_BYTES = 4
 | 
			
		||||
 | 
			
		||||
type tunWriter struct {
 | 
			
		||||
	phony.Inbox
 | 
			
		||||
	tun *TunAdapter
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +22,8 @@ func (w *tunWriter) writeFrom(from phony.Actor, b []byte) {
 | 
			
		|||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// write is pretty loose with the memory safety rules, e.g. it assumes it can read w.tun.iface.IsTap() safely
 | 
			
		||||
// write is pretty loose with the memory safety rules, e.g. it assumes it can
 | 
			
		||||
// read w.tun.iface.IsTap() safely
 | 
			
		||||
func (w *tunWriter) _write(b []byte) {
 | 
			
		||||
	var written int
 | 
			
		||||
	var err error
 | 
			
		||||
| 
						 | 
				
			
			@ -33,72 +31,17 @@ func (w *tunWriter) _write(b []byte) {
 | 
			
		|||
	if n == 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if w.tun.iface.IsTAP() {
 | 
			
		||||
		sendndp := func(dstAddr address.Address) {
 | 
			
		||||
			neigh, known := w.tun.icmpv6.getNeighbor(dstAddr)
 | 
			
		||||
			known = known && (time.Since(neigh.lastsolicitation).Seconds() < 30)
 | 
			
		||||
			if !known {
 | 
			
		||||
				w.tun.icmpv6.Solicit(dstAddr)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		peermac := net.HardwareAddr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 | 
			
		||||
		var dstAddr address.Address
 | 
			
		||||
		var peerknown bool
 | 
			
		||||
		if b[0]&0xf0 == 0x40 {
 | 
			
		||||
			dstAddr = w.tun.addr
 | 
			
		||||
		} else if b[0]&0xf0 == 0x60 {
 | 
			
		||||
			if !bytes.Equal(w.tun.addr[:16], dstAddr[:16]) && !bytes.Equal(w.tun.subnet[:8], dstAddr[:8]) {
 | 
			
		||||
				dstAddr = w.tun.addr
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if neighbor, ok := w.tun.icmpv6.getNeighbor(dstAddr); ok && neighbor.learned {
 | 
			
		||||
			// If we've learned the MAC of a 300::/7 address, for example, or a CKR
 | 
			
		||||
			// address, use the MAC address of that
 | 
			
		||||
			peermac = neighbor.mac
 | 
			
		||||
			peerknown = true
 | 
			
		||||
		} else if neighbor, ok := w.tun.icmpv6.getNeighbor(w.tun.addr); ok && neighbor.learned {
 | 
			
		||||
			// Otherwise send directly to the MAC address of the host if that's
 | 
			
		||||
			// known instead
 | 
			
		||||
			peermac = neighbor.mac
 | 
			
		||||
			peerknown = true
 | 
			
		||||
		} else {
 | 
			
		||||
			// Nothing has been discovered, try to discover the destination
 | 
			
		||||
			sendndp(w.tun.addr)
 | 
			
		||||
		}
 | 
			
		||||
		if peerknown {
 | 
			
		||||
			var proto ethernet.Ethertype
 | 
			
		||||
			switch {
 | 
			
		||||
			case b[0]&0xf0 == 0x60:
 | 
			
		||||
				proto = ethernet.IPv6
 | 
			
		||||
			case b[0]&0xf0 == 0x40:
 | 
			
		||||
				proto = ethernet.IPv4
 | 
			
		||||
			}
 | 
			
		||||
			var frame ethernet.Frame
 | 
			
		||||
			frame.Prepare(
 | 
			
		||||
				peermac[:6],            // Destination MAC address
 | 
			
		||||
				w.tun.icmpv6.mymac[:6], // Source MAC address
 | 
			
		||||
				ethernet.NotTagged,     // VLAN tagging
 | 
			
		||||
				proto,                  // Ethertype
 | 
			
		||||
				len(b))                 // Payload length
 | 
			
		||||
			copy(frame[tun_ETHER_HEADER_LENGTH:], b[:n])
 | 
			
		||||
			n += tun_ETHER_HEADER_LENGTH
 | 
			
		||||
			written, err = w.tun.iface.Write(frame[:n])
 | 
			
		||||
		} else {
 | 
			
		||||
			w.tun.log.Errorln("TUN/TAP iface write error: no peer MAC known for", net.IP(dstAddr[:]).String(), "- dropping packet")
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		written, err = w.tun.iface.Write(b[:n])
 | 
			
		||||
		util.PutBytes(b)
 | 
			
		||||
	}
 | 
			
		||||
	written, err = w.tun.iface.Write(append([]byte{0, 0, 0, 0}, b[:n]...), TUN_OFFSET_BYTES)
 | 
			
		||||
	util.PutBytes(b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		w.tun.Act(w, func() {
 | 
			
		||||
			if !w.tun.isOpen {
 | 
			
		||||
				w.tun.log.Errorln("TUN/TAP iface write error:", err)
 | 
			
		||||
				w.tun.log.Errorln("TUN iface write error:", err)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	if written != n {
 | 
			
		||||
		w.tun.log.Errorln("TUN/TAP iface write mismatch:", written, "bytes written vs", n, "bytes given")
 | 
			
		||||
	if written-TUN_OFFSET_BYTES != n {
 | 
			
		||||
		w.tun.log.Errorln("TUN iface write mismatch:", written-TUN_OFFSET_BYTES, "bytes written vs", n, "bytes given")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -109,13 +52,18 @@ type tunReader struct {
 | 
			
		|||
 | 
			
		||||
func (r *tunReader) _read() {
 | 
			
		||||
	// Get a slice to store the packet in
 | 
			
		||||
	recvd := util.ResizeBytes(util.GetBytes(), 65535+tun_ETHER_HEADER_LENGTH)
 | 
			
		||||
	// Wait for a packet to be delivered to us through the TUN/TAP adapter
 | 
			
		||||
	n, err := r.tun.iface.Read(recvd)
 | 
			
		||||
	if n <= 0 {
 | 
			
		||||
	recvd := util.ResizeBytes(util.GetBytes(), r.tun.mtu+TUN_OFFSET_BYTES)
 | 
			
		||||
	// Wait for a packet to be delivered to us through the TUN adapter
 | 
			
		||||
	n, err := r.tun.iface.Read(recvd, TUN_OFFSET_BYTES)
 | 
			
		||||
	if n <= TUN_OFFSET_BYTES || err != nil {
 | 
			
		||||
		r.tun.log.Errorln("Error reading TUN:", err)
 | 
			
		||||
		err = r.tun.iface.Flush()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			r.tun.log.Errorln("Unable to flush packets:", err)
 | 
			
		||||
		}
 | 
			
		||||
		util.PutBytes(recvd)
 | 
			
		||||
	} else {
 | 
			
		||||
		r.tun.handlePacketFrom(r, recvd[:n], err)
 | 
			
		||||
		r.tun.handlePacketFrom(r, recvd[TUN_OFFSET_BYTES:n+TUN_OFFSET_BYTES], err)
 | 
			
		||||
	}
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		// Now read again
 | 
			
		||||
| 
						 | 
				
			
			@ -132,43 +80,17 @@ func (tun *TunAdapter) handlePacketFrom(from phony.Actor, packet []byte, err err
 | 
			
		|||
// does the work of reading a packet and sending it to the correct tunConn
 | 
			
		||||
func (tun *TunAdapter) _handlePacket(recvd []byte, err error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		tun.log.Errorln("TUN/TAP iface read error:", err)
 | 
			
		||||
		tun.log.Errorln("TUN iface read error:", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// If it's a TAP adapter, update the buffer slice so that we no longer
 | 
			
		||||
	// include the ethernet headers
 | 
			
		||||
	offset := 0
 | 
			
		||||
	if tun.iface.IsTAP() {
 | 
			
		||||
		// Set our offset to beyond the ethernet headers
 | 
			
		||||
		offset = tun_ETHER_HEADER_LENGTH
 | 
			
		||||
		// Check first of all that we can go beyond the ethernet headers
 | 
			
		||||
		if len(recvd) <= offset {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// Offset the buffer from now on so that we can ignore ethernet frames if
 | 
			
		||||
	// they are present
 | 
			
		||||
	bs := recvd[offset:]
 | 
			
		||||
	bs := recvd[:]
 | 
			
		||||
	// Check if the packet is long enough to detect if it's an ICMP packet or not
 | 
			
		||||
	if len(bs) < 7 {
 | 
			
		||||
		tun.log.Traceln("TUN/TAP iface read undersized unknown packet, length:", len(bs))
 | 
			
		||||
		tun.log.Traceln("TUN iface read undersized unknown packet, length:", len(bs))
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// If we detect an ICMP packet then hand it to the ICMPv6 module
 | 
			
		||||
	if bs[6] == 58 {
 | 
			
		||||
		// Found an ICMPv6 packet - we need to make sure to give ICMPv6 the full
 | 
			
		||||
		// Ethernet frame rather than just the IPv6 packet as this is needed for
 | 
			
		||||
		// NDP to work correctly
 | 
			
		||||
		if err := tun.icmpv6.ParsePacket(recvd); err == nil {
 | 
			
		||||
			// We acted on the packet in the ICMPv6 module so don't forward or do
 | 
			
		||||
			// anything else with it
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if offset != 0 {
 | 
			
		||||
		// Shift forward to avoid leaking bytes off the front of the slice when we eventually store it
 | 
			
		||||
		bs = append(recvd[:0], bs...)
 | 
			
		||||
	}
 | 
			
		||||
	// From the IP header, work out what our source and destination addresses
 | 
			
		||||
	// and node IDs are. We will need these in order to work out where to send
 | 
			
		||||
	// the packet
 | 
			
		||||
| 
						 | 
				
			
			@ -181,7 +103,7 @@ func (tun *TunAdapter) _handlePacket(recvd []byte, err error) {
 | 
			
		|||
	if bs[0]&0xf0 == 0x60 {
 | 
			
		||||
		// Check if we have a fully-sized IPv6 header
 | 
			
		||||
		if len(bs) < 40 {
 | 
			
		||||
			tun.log.Traceln("TUN/TAP iface read undersized ipv6 packet, length:", len(bs))
 | 
			
		||||
			tun.log.Traceln("TUN iface read undersized ipv6 packet, length:", len(bs))
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		// Check the packet size
 | 
			
		||||
| 
						 | 
				
			
			@ -195,7 +117,7 @@ func (tun *TunAdapter) _handlePacket(recvd []byte, err error) {
 | 
			
		|||
	} else if bs[0]&0xf0 == 0x40 {
 | 
			
		||||
		// Check if we have a fully-sized IPv4 header
 | 
			
		||||
		if len(bs) < 20 {
 | 
			
		||||
			tun.log.Traceln("TUN/TAP iface read undersized ipv4 packet, length:", len(bs))
 | 
			
		||||
			tun.log.Traceln("TUN iface read undersized ipv4 packet, length:", len(bs))
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		// Check the packet size
 | 
			
		||||
| 
						 | 
				
			
			@ -267,7 +189,7 @@ func (tun *TunAdapter) _handlePacket(recvd []byte, err error) {
 | 
			
		|||
					if tc, err = tun._wrap(conn.(*yggdrasil.Conn)); err != nil {
 | 
			
		||||
						// Something went wrong when storing the connection, typically that
 | 
			
		||||
						// something already exists for this address or subnet
 | 
			
		||||
						tun.log.Debugln("TUN/TAP iface wrap:", err)
 | 
			
		||||
						tun.log.Debugln("TUN iface wrap:", err)
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
					for _, packet := range packets {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/Arceliar/phony"
 | 
			
		||||
	"github.com/gologme/log"
 | 
			
		||||
	"github.com/yggdrasil-network/water"
 | 
			
		||||
	"golang.zx2c4.com/wireguard/tun"
 | 
			
		||||
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/config"
 | 
			
		||||
| 
						 | 
				
			
			@ -28,12 +28,11 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
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().
 | 
			
		||||
// TunAdapter represents a running TUN interface and extends the
 | 
			
		||||
// yggdrasil.Adapter type. In order to use the TUN adapter with Yggdrasil, you
 | 
			
		||||
// should pass this object to the yggdrasil.SetRouterAdapter() function before
 | 
			
		||||
// calling yggdrasil.Start().
 | 
			
		||||
type TunAdapter struct {
 | 
			
		||||
	core        *yggdrasil.Core
 | 
			
		||||
	writer      tunWriter
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +47,7 @@ type TunAdapter struct {
 | 
			
		|||
	ckr         cryptokey
 | 
			
		||||
	icmpv6      ICMPv6
 | 
			
		||||
	mtu         int
 | 
			
		||||
	iface       *water.Interface
 | 
			
		||||
	iface       tun.Device
 | 
			
		||||
	phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below
 | 
			
		||||
	//mutex        sync.RWMutex // Protects the below
 | 
			
		||||
	addrToConn   map[address.Address]*tunConn
 | 
			
		||||
| 
						 | 
				
			
			@ -64,12 +63,12 @@ type TunOptions struct {
 | 
			
		|||
 | 
			
		||||
// Gets the maximum supported MTU for the platform based on the defaults in
 | 
			
		||||
// defaults.GetDefaults().
 | 
			
		||||
func getSupportedMTU(mtu int, istapmode bool) int {
 | 
			
		||||
func getSupportedMTU(mtu int) int {
 | 
			
		||||
	if mtu < 1280 {
 | 
			
		||||
		return 1280
 | 
			
		||||
	}
 | 
			
		||||
	if mtu > MaximumMTU(istapmode) {
 | 
			
		||||
		return MaximumMTU(istapmode)
 | 
			
		||||
	if mtu > MaximumMTU() {
 | 
			
		||||
		return MaximumMTU()
 | 
			
		||||
	}
 | 
			
		||||
	return mtu
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -77,55 +76,38 @@ func getSupportedMTU(mtu int, istapmode bool) int {
 | 
			
		|||
// 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()
 | 
			
		||||
	if name, err := tun.iface.Name(); err == nil {
 | 
			
		||||
		return name
 | 
			
		||||
	}
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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, tun.IsTAP())
 | 
			
		||||
	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.
 | 
			
		||||
// DefaultName gets the default TUN 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
 | 
			
		||||
// DefaultMTU gets the default TUN interface MTU for your platform. This can
 | 
			
		||||
// be as high as MaximumMTU(), depending on platform, but is never lower than 1280.
 | 
			
		||||
func DefaultMTU() int {
 | 
			
		||||
	ehbytes := 0
 | 
			
		||||
	if DefaultIsTAP() {
 | 
			
		||||
		ehbytes = tun_ETHER_HEADER_LENGTH
 | 
			
		||||
	}
 | 
			
		||||
	return defaults.GetDefaults().DefaultIfMTU - ehbytes
 | 
			
		||||
	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
 | 
			
		||||
// MaximumMTU returns the maximum supported TUN interface MTU for your
 | 
			
		||||
// platform. This can be as high as 65535, depending on platform, but is never
 | 
			
		||||
// lower than 1280.
 | 
			
		||||
func MaximumMTU(iftapmode bool) int {
 | 
			
		||||
	ehbytes := 0
 | 
			
		||||
	if iftapmode {
 | 
			
		||||
		ehbytes = tun_ETHER_HEADER_LENGTH
 | 
			
		||||
	}
 | 
			
		||||
	return defaults.GetDefaults().MaximumIfMTU - ehbytes
 | 
			
		||||
func MaximumMTU() int {
 | 
			
		||||
	return defaults.GetDefaults().MaximumIfMTU
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Init initialises the TUN/TAP module. You must have acquired a Listener from
 | 
			
		||||
// Init initialises the TUN module. You must have acquired a Listener from
 | 
			
		||||
// the Yggdrasil core before this point and it must not be in use elsewhere.
 | 
			
		||||
func (tun *TunAdapter) Init(core *yggdrasil.Core, config *config.NodeState, log *log.Logger, options interface{}) error {
 | 
			
		||||
	tunoptions, ok := options.(TunOptions)
 | 
			
		||||
| 
						 | 
				
			
			@ -145,7 +127,7 @@ func (tun *TunAdapter) Init(core *yggdrasil.Core, config *config.NodeState, log
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Start the setup process for the TUN/TAP adapter. If successful, starts the
 | 
			
		||||
// Start the setup process for the TUN adapter. If successful, starts the
 | 
			
		||||
// reader actor to handle packets on that interface.
 | 
			
		||||
func (tun *TunAdapter) Start() error {
 | 
			
		||||
	var err error
 | 
			
		||||
| 
						 | 
				
			
			@ -157,11 +139,11 @@ func (tun *TunAdapter) Start() error {
 | 
			
		|||
 | 
			
		||||
func (tun *TunAdapter) _start() error {
 | 
			
		||||
	if tun.isOpen {
 | 
			
		||||
		return errors.New("TUN/TAP module is already started")
 | 
			
		||||
		return errors.New("TUN module is already started")
 | 
			
		||||
	}
 | 
			
		||||
	current := tun.config.GetCurrent()
 | 
			
		||||
	if tun.config == nil || tun.listener == nil || tun.dialer == nil {
 | 
			
		||||
		return errors.New("no configuration available to TUN/TAP")
 | 
			
		||||
		return errors.New("no configuration available to TUN")
 | 
			
		||||
	}
 | 
			
		||||
	var boxPub crypto.BoxPubKey
 | 
			
		||||
	boxPubHex, err := hex.DecodeString(current.EncryptionPublicKey)
 | 
			
		||||
| 
						 | 
				
			
			@ -174,23 +156,19 @@ func (tun *TunAdapter) _start() error {
 | 
			
		|||
	tun.subnet = *address.SubnetForNodeID(nodeID)
 | 
			
		||||
	addr := fmt.Sprintf("%s/%d", net.IP(tun.addr[:]).String(), 8*len(address.GetPrefix())-1)
 | 
			
		||||
	if current.IfName == "none" || current.IfName == "dummy" {
 | 
			
		||||
		tun.log.Debugln("Not starting TUN/TAP as ifname is none or dummy")
 | 
			
		||||
		tun.log.Debugln("Not starting TUN as ifname is none or dummy")
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if err := tun.setup(current.IfName, current.IfTAPMode, addr, current.IfMTU); err != nil {
 | 
			
		||||
	if err := tun.setup(current.IfName, addr, current.IfMTU); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if tun.MTU() != current.IfMTU {
 | 
			
		||||
		tun.log.Warnf("Warning: Interface MTU %d automatically adjusted to %d (supported range is 1280-%d)", current.IfMTU, tun.MTU(), MaximumMTU(tun.IsTAP()))
 | 
			
		||||
		tun.log.Warnf("Warning: Interface MTU %d automatically adjusted to %d (supported range is 1280-%d)", current.IfMTU, tun.MTU(), MaximumMTU())
 | 
			
		||||
	}
 | 
			
		||||
	tun.core.SetMaximumSessionMTU(uint16(tun.MTU()))
 | 
			
		||||
	tun.isOpen = true
 | 
			
		||||
	go tun.handler()
 | 
			
		||||
	tun.reader.Act(nil, tun.reader._read) // Start the reader
 | 
			
		||||
	tun.icmpv6.Init(tun)
 | 
			
		||||
	if tun.IsTAP() {
 | 
			
		||||
		go tun.icmpv6.Solicit(tun.addr)
 | 
			
		||||
	}
 | 
			
		||||
	tun.ckr.init(tun)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -204,7 +182,7 @@ func (tun *TunAdapter) IsStarted() bool {
 | 
			
		|||
	return isOpen
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Start the setup process for the TUN/TAP adapter. If successful, starts the
 | 
			
		||||
// Start the setup process for the TUN adapter. If successful, starts the
 | 
			
		||||
// read/write goroutines to handle packets on that interface.
 | 
			
		||||
func (tun *TunAdapter) Stop() error {
 | 
			
		||||
	var err error
 | 
			
		||||
| 
						 | 
				
			
			@ -216,7 +194,7 @@ func (tun *TunAdapter) Stop() error {
 | 
			
		|||
 | 
			
		||||
func (tun *TunAdapter) _stop() error {
 | 
			
		||||
	tun.isOpen = false
 | 
			
		||||
	// by TUN/TAP, e.g. readers/writers, sessions
 | 
			
		||||
	// by TUN, e.g. readers/writers, sessions
 | 
			
		||||
	if tun.iface != nil {
 | 
			
		||||
		// Just in case we failed to start up the iface for some reason, this can apparently happen on Windows
 | 
			
		||||
		tun.iface.Close()
 | 
			
		||||
| 
						 | 
				
			
			@ -224,16 +202,16 @@ func (tun *TunAdapter) _stop() error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateConfig updates the TUN/TAP module with the provided config.NodeConfig
 | 
			
		||||
// UpdateConfig updates the TUN module with the provided config.NodeConfig
 | 
			
		||||
// and then signals the various module goroutines to reconfigure themselves if
 | 
			
		||||
// needed.
 | 
			
		||||
func (tun *TunAdapter) UpdateConfig(config *config.NodeConfig) {
 | 
			
		||||
	tun.log.Debugln("Reloading TUN/TAP configuration...")
 | 
			
		||||
	tun.log.Debugln("Reloading TUN configuration...")
 | 
			
		||||
 | 
			
		||||
	// Replace the active configuration with the supplied one
 | 
			
		||||
	tun.config.Replace(*config)
 | 
			
		||||
 | 
			
		||||
	// If the MTU has changed in the TUN/TAP module then this is where we would
 | 
			
		||||
	// If the MTU has changed in the TUN module then this is where we would
 | 
			
		||||
	// tell the router so that updated session pings can be sent. However, we
 | 
			
		||||
	// don't currently update the MTU of the adapter once it has been created so
 | 
			
		||||
	// this doesn't actually happen in the real world yet.
 | 
			
		||||
| 
						 | 
				
			
			@ -248,14 +226,14 @@ func (tun *TunAdapter) handler() error {
 | 
			
		|||
		// Accept the incoming connection
 | 
			
		||||
		conn, err := tun.listener.Accept()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			tun.log.Errorln("TUN/TAP connection accept error:", err)
 | 
			
		||||
			tun.log.Errorln("TUN connection accept error:", err)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		phony.Block(tun, func() {
 | 
			
		||||
			if _, err := tun._wrap(conn.(*yggdrasil.Conn)); err != nil {
 | 
			
		||||
				// Something went wrong when storing the connection, typically that
 | 
			
		||||
				// something already exists for this address or subnet
 | 
			
		||||
				tun.log.Debugln("TUN/TAP handler wrap:", err)
 | 
			
		||||
				tun.log.Debugln("TUN handler wrap:", err)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
// +build openbsd freebsd netbsd
 | 
			
		||||
// +build openbsd freebsd
 | 
			
		||||
 | 
			
		||||
package tuntap
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
 | 
			
		||||
	"github.com/yggdrasil-network/water"
 | 
			
		||||
	wgtun "golang.zx2c4.com/wireguard/tun"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const SIOCSIFADDR_IN6 = (0x80000000) | ((288 & 0x1fff) << 16) | uint32(byte('i'))<<8 | 12
 | 
			
		||||
| 
						 | 
				
			
			@ -72,34 +72,18 @@ type in6_ifreq_lifetime struct {
 | 
			
		|||
	ifru_addrlifetime in6_addrlifetime
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sets the IPv6 address of the utun adapter. On all BSD platforms (FreeBSD,
 | 
			
		||||
// OpenBSD, NetBSD) an attempt is made to set the adapter properties by using
 | 
			
		||||
// a system socket and making syscalls to the kernel. This is not refined though
 | 
			
		||||
// and often doesn't work (if at all), therefore if a call fails, it resorts
 | 
			
		||||
// to calling "ifconfig" instead.
 | 
			
		||||
func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int) error {
 | 
			
		||||
	var config water.Config
 | 
			
		||||
	if ifname[:4] == "auto" {
 | 
			
		||||
		ifname = "/dev/tap0"
 | 
			
		||||
	}
 | 
			
		||||
	if len(ifname) < 9 {
 | 
			
		||||
		panic("TUN/TAP name must be in format /dev/tunX or /dev/tapX")
 | 
			
		||||
	}
 | 
			
		||||
	switch {
 | 
			
		||||
	case iftapmode || ifname[:8] == "/dev/tap":
 | 
			
		||||
		config = water.Config{DeviceType: water.TAP}
 | 
			
		||||
	case !iftapmode || ifname[:8] == "/dev/tun":
 | 
			
		||||
		panic("TUN mode is not currently supported on this platform, please use TAP instead")
 | 
			
		||||
	default:
 | 
			
		||||
		panic("TUN/TAP name must be in format /dev/tunX or /dev/tapX")
 | 
			
		||||
	}
 | 
			
		||||
	config.Name = ifname
 | 
			
		||||
	iface, err := water.New(config)
 | 
			
		||||
// Configures the TUN adapter with the correct IPv6 address and MTU.
 | 
			
		||||
func (tun *TunAdapter) setup(ifname string, addr string, mtu int) error {
 | 
			
		||||
	iface, err := wgtun.CreateTUN(ifname, mtu)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	tun.iface = iface
 | 
			
		||||
	tun.mtu = getSupportedMTU(mtu, iftapmode)
 | 
			
		||||
	if mtu, err := iface.MTU(); err == nil {
 | 
			
		||||
		tun.mtu = getSupportedMTU(mtu)
 | 
			
		||||
	} else {
 | 
			
		||||
		tun.mtu = 0
 | 
			
		||||
	}
 | 
			
		||||
	return tun.setupAddress(addr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,22 +12,21 @@ import (
 | 
			
		|||
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
 | 
			
		||||
	water "github.com/yggdrasil-network/water"
 | 
			
		||||
	wgtun "golang.zx2c4.com/wireguard/tun"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Configures the "utun" adapter with the correct IPv6 address and MTU.
 | 
			
		||||
func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int) error {
 | 
			
		||||
	if iftapmode {
 | 
			
		||||
		tun.log.Warnln("Warning: TAP mode is not supported on this platform, defaulting to TUN")
 | 
			
		||||
		iftapmode = false
 | 
			
		||||
	}
 | 
			
		||||
	config := water.Config{DeviceType: water.TUN}
 | 
			
		||||
	iface, err := water.New(config)
 | 
			
		||||
func (tun *TunAdapter) setup(ifname string, addr string, mtu int) error {
 | 
			
		||||
	iface, err := wgtun.CreateTUN(ifname, mtu)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	tun.iface = iface
 | 
			
		||||
	tun.mtu = getSupportedMTU(mtu, iftapmode)
 | 
			
		||||
	if mtu, err := iface.MTU(); err == nil {
 | 
			
		||||
		tun.mtu = getSupportedMTU(mtu)
 | 
			
		||||
	} else {
 | 
			
		||||
		tun.mtu = 0
 | 
			
		||||
	}
 | 
			
		||||
	return tun.setupAddress(addr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +79,7 @@ func (tun *TunAdapter) setupAddress(addr string) error {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	var ar in6_aliasreq
 | 
			
		||||
	copy(ar.ifra_name[:], tun.iface.Name())
 | 
			
		||||
	copy(ar.ifra_name[:], tun.Name())
 | 
			
		||||
 | 
			
		||||
	ar.ifra_prefixmask.sin6_len = uint8(unsafe.Sizeof(ar.ifra_prefixmask))
 | 
			
		||||
	b := make([]byte, 16)
 | 
			
		||||
| 
						 | 
				
			
			@ -104,7 +103,7 @@ func (tun *TunAdapter) setupAddress(addr string) error {
 | 
			
		|||
	ar.ifra_lifetime.ia6t_pltime = darwin_ND6_INFINITE_LIFETIME
 | 
			
		||||
 | 
			
		||||
	var ir ifreq
 | 
			
		||||
	copy(ir.ifr_name[:], tun.iface.Name())
 | 
			
		||||
	copy(ir.ifr_name[:], tun.Name())
 | 
			
		||||
	ir.ifru_mtu = uint32(tun.mtu)
 | 
			
		||||
 | 
			
		||||
	tun.log.Infof("Interface name: %s", ar.ifra_name)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,31 +6,21 @@ package tuntap
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/vishvananda/netlink"
 | 
			
		||||
 | 
			
		||||
	water "github.com/yggdrasil-network/water"
 | 
			
		||||
	wgtun "golang.zx2c4.com/wireguard/tun"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Configures the TAP adapter with the correct IPv6 address and MTU.
 | 
			
		||||
func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int) error {
 | 
			
		||||
	var config water.Config
 | 
			
		||||
	if iftapmode {
 | 
			
		||||
		config = water.Config{DeviceType: water.TAP}
 | 
			
		||||
	} else {
 | 
			
		||||
		config = water.Config{DeviceType: water.TUN}
 | 
			
		||||
	}
 | 
			
		||||
	if ifname != "" && ifname != "auto" {
 | 
			
		||||
		config.Name = ifname
 | 
			
		||||
	}
 | 
			
		||||
	iface, err := water.New(config)
 | 
			
		||||
// Configures the TUN adapter with the correct IPv6 address and MTU.
 | 
			
		||||
func (tun *TunAdapter) setup(ifname string, addr string, mtu int) error {
 | 
			
		||||
	iface, err := wgtun.CreateTUN(ifname, mtu)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	tun.iface = iface
 | 
			
		||||
	tun.mtu = getSupportedMTU(mtu, iftapmode)
 | 
			
		||||
	// Friendly output
 | 
			
		||||
	tun.log.Infof("Interface name: %s", tun.iface.Name())
 | 
			
		||||
	tun.log.Infof("Interface IPv6: %s", addr)
 | 
			
		||||
	tun.log.Infof("Interface MTU: %d", tun.mtu)
 | 
			
		||||
	if mtu, err := iface.MTU(); err == nil {
 | 
			
		||||
		tun.mtu = getSupportedMTU(mtu)
 | 
			
		||||
	} else {
 | 
			
		||||
		tun.mtu = 0
 | 
			
		||||
	}
 | 
			
		||||
	return tun.setupAddress(addr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -56,5 +46,9 @@ func (tun *TunAdapter) setupAddress(addr string) error {
 | 
			
		|||
	if err := netlink.LinkSetUp(nlintf); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// Friendly output
 | 
			
		||||
	tun.log.Infof("Interface name: %s", tun.iface.Name())
 | 
			
		||||
	tun.log.Infof("Interface IPv6: %s", addr)
 | 
			
		||||
	tun.log.Infof("Interface MTU: %d", tun.mtu)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,27 +1,26 @@
 | 
			
		|||
// +build !linux,!darwin,!windows,!openbsd,!freebsd,!netbsd,!mobile
 | 
			
		||||
// +build !linux,!darwin,!windows,!openbsd,!freebsd,!mobile
 | 
			
		||||
 | 
			
		||||
package tuntap
 | 
			
		||||
 | 
			
		||||
import water "github.com/yggdrasil-network/water"
 | 
			
		||||
 | 
			
		||||
// This is to catch unsupported platforms
 | 
			
		||||
// If your platform supports tun devices, you could try configuring it manually
 | 
			
		||||
 | 
			
		||||
// Creates the TUN/TAP adapter, if supported by the Water library. Note that
 | 
			
		||||
// no guarantees are made at this point on an unsupported platform.
 | 
			
		||||
func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int) error {
 | 
			
		||||
	var config water.Config
 | 
			
		||||
	if iftapmode {
 | 
			
		||||
		config = water.Config{DeviceType: water.TAP}
 | 
			
		||||
	} else {
 | 
			
		||||
		config = water.Config{DeviceType: water.TUN}
 | 
			
		||||
	}
 | 
			
		||||
	iface, err := water.New(config)
 | 
			
		||||
import (
 | 
			
		||||
	wgtun "golang.zx2c4.com/wireguard/tun"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Configures the TUN adapter with the correct IPv6 address and MTU.
 | 
			
		||||
func (tun *TunAdapter) setup(ifname string, addr string, mtu int) error {
 | 
			
		||||
	iface, err := wgtun.CreateTUN(ifname, mtu)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	tun.iface = iface
 | 
			
		||||
	tun.mtu = getSupportedMTU(mtu, iftapmode)
 | 
			
		||||
	if mtu, err := iface.MTU(); err == nil {
 | 
			
		||||
		tun.mtu = getSupportedMTU(mtu)
 | 
			
		||||
	} else {
 | 
			
		||||
		tun.mtu = 0
 | 
			
		||||
	}
 | 
			
		||||
	return tun.setupAddress(addr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,69 +7,23 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	water "github.com/yggdrasil-network/water"
 | 
			
		||||
	wgtun "golang.zx2c4.com/wireguard/tun"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// This is to catch Windows platforms
 | 
			
		||||
 | 
			
		||||
// Configures the TAP adapter with the correct IPv6 address and MTU. On Windows
 | 
			
		||||
// we don't make use of a direct operating system API to do this - we instead
 | 
			
		||||
// delegate the hard work to "netsh".
 | 
			
		||||
func (tun *TunAdapter) setup(ifname string, iftapmode bool, addr string, mtu int) error {
 | 
			
		||||
	if !iftapmode {
 | 
			
		||||
		tun.log.Warnln("Warning: TUN mode is not supported on this platform, defaulting to TAP")
 | 
			
		||||
		iftapmode = true
 | 
			
		||||
	}
 | 
			
		||||
	config := water.Config{DeviceType: water.TAP}
 | 
			
		||||
	config.PlatformSpecificParams.ComponentID = "tap0901"
 | 
			
		||||
	config.PlatformSpecificParams.Network = "169.254.0.1/32"
 | 
			
		||||
	if ifname == "auto" {
 | 
			
		||||
		config.PlatformSpecificParams.InterfaceName = ""
 | 
			
		||||
	} else {
 | 
			
		||||
		config.PlatformSpecificParams.InterfaceName = ifname
 | 
			
		||||
	}
 | 
			
		||||
	iface, err := water.New(config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if iface.Name() == "" {
 | 
			
		||||
		return errors.New("unable to find TAP adapter with component ID " + config.PlatformSpecificParams.ComponentID)
 | 
			
		||||
	}
 | 
			
		||||
	// Reset the adapter - this invalidates iface so we'll need to get a new one
 | 
			
		||||
	cmd := exec.Command("netsh", "interface", "set", "interface", iface.Name(), "admin=DISABLED")
 | 
			
		||||
	tun.log.Debugln("netsh command:", strings.Join(cmd.Args, " "))
 | 
			
		||||
	output, err := cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		tun.log.Errorln("Windows netsh failed:", err)
 | 
			
		||||
		tun.log.Traceln(string(output))
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	time.Sleep(time.Second) // FIXME artifical delay to give netsh time to take effect
 | 
			
		||||
	// Bring the interface back up
 | 
			
		||||
	cmd = exec.Command("netsh", "interface", "set", "interface", iface.Name(), "admin=ENABLED")
 | 
			
		||||
	tun.log.Debugln("netsh command:", strings.Join(cmd.Args, " "))
 | 
			
		||||
	output, err = cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		tun.log.Errorln("Windows netsh failed:", err)
 | 
			
		||||
		tun.log.Traceln(string(output))
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	time.Sleep(time.Second) // FIXME artifical delay to give netsh time to take effect
 | 
			
		||||
	// Get a new iface
 | 
			
		||||
	iface, err = water.New(config)
 | 
			
		||||
// Configures the TUN adapter with the correct IPv6 address and MTU.
 | 
			
		||||
func (tun *TunAdapter) setup(ifname string, addr string, mtu int) error {
 | 
			
		||||
	iface, err := wgtun.CreateTUN(ifname, mtu)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	tun.iface = iface
 | 
			
		||||
	tun.mtu = getSupportedMTU(mtu, iftapmode)
 | 
			
		||||
	err = tun.setupMTU(tun.mtu)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	if mtu, err := iface.MTU(); err == nil {
 | 
			
		||||
		tun.mtu = getSupportedMTU(mtu)
 | 
			
		||||
	} else {
 | 
			
		||||
		tun.mtu = 0
 | 
			
		||||
	}
 | 
			
		||||
	// Friendly output
 | 
			
		||||
	tun.log.Infof("Interface name: %s", tun.iface.Name())
 | 
			
		||||
	tun.log.Infof("Interface IPv6: %s", addr)
 | 
			
		||||
	tun.log.Infof("Interface MTU: %d", tun.mtu)
 | 
			
		||||
	return tun.setupAddress(addr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue