add
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
/* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2017-2025 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package device
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
|
||||
"golang.zx2c4.com/wireguard/conn"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
)
|
||||
|
||||
// MultiPathConfig represents configuration for multi-path networking
|
||||
type MultiPathConfig struct {
|
||||
// InterfaceIndexes are the network interface indexes to bind to
|
||||
// If empty, uses default interface selection
|
||||
InterfaceIndexes []uint32
|
||||
// BindFactory creates new Bind instances. If nil, uses conn.NewStdNetBind()
|
||||
BindFactory func() conn.Bind
|
||||
}
|
||||
|
||||
// NewMultiPathDevice creates a new WireGuard device with multi-path networking
|
||||
// It creates separate bind instances for each specified network interface
|
||||
func NewMultiPathDevice(tunDevice tun.Device, config MultiPathConfig, logger *Logger) (*Device, error) {
|
||||
if len(config.InterfaceIndexes) == 0 {
|
||||
return nil, fmt.Errorf("MultiPathConfig must specify at least one interface index")
|
||||
}
|
||||
|
||||
// Use default bind factory if none specified
|
||||
bindFactory := config.BindFactory
|
||||
if bindFactory == nil {
|
||||
bindFactory = func() conn.Bind {
|
||||
return conn.NewStdNetBind()
|
||||
}
|
||||
}
|
||||
|
||||
// Create a bind for each interface
|
||||
binds := make([]conn.Bind, len(config.InterfaceIndexes))
|
||||
for i := range config.InterfaceIndexes {
|
||||
binds[i] = bindFactory()
|
||||
}
|
||||
|
||||
// Create multi-path bind
|
||||
multiPathBind := conn.NewMultiPathBind(binds)
|
||||
|
||||
// Configure each bind to use its specific interface
|
||||
for i, interfaceIndex := range config.InterfaceIndexes {
|
||||
err := multiPathBind.BindToInterface(i, interfaceIndex, false)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to bind to interface %d: %v", interfaceIndex, err)
|
||||
// Continue with other interfaces rather than failing completely
|
||||
} else {
|
||||
logger.Verbosef("Bound network path %d to interface index %d", i, interfaceIndex)
|
||||
}
|
||||
}
|
||||
|
||||
// Create device with multi-path bind
|
||||
device := NewDevice(tunDevice, multiPathBind, logger)
|
||||
|
||||
logger.Verbosef("Created multi-path WireGuard device with %d network paths", len(config.InterfaceIndexes))
|
||||
return device, nil
|
||||
}
|
||||
|
||||
// NewMultiPathDeviceByNames creates a multi-path device using interface names instead of indexes
|
||||
func NewMultiPathDeviceByNames(tunDevice tun.Device, interfaceNames []string, logger *Logger) (*Device, error) {
|
||||
if len(interfaceNames) == 0 {
|
||||
return nil, fmt.Errorf("must specify at least one interface name")
|
||||
}
|
||||
|
||||
// Convert interface names to indexes
|
||||
interfaceIndexes := make([]uint32, len(interfaceNames))
|
||||
for i, name := range interfaceNames {
|
||||
iface, err := net.InterfaceByName(name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find interface %s: %w", name, err)
|
||||
}
|
||||
interfaceIndexes[i] = uint32(iface.Index)
|
||||
logger.Verbosef("Interface %s has index %d", name, iface.Index)
|
||||
}
|
||||
|
||||
config := MultiPathConfig{
|
||||
InterfaceIndexes: interfaceIndexes,
|
||||
}
|
||||
|
||||
return NewMultiPathDevice(tunDevice, config, logger)
|
||||
}
|
||||
|
||||
// GetNetworkInterfaceInfo returns information about available network interfaces
|
||||
func GetNetworkInterfaceInfo() ([]NetworkInterfaceInfo, error) {
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list network interfaces: %w", err)
|
||||
}
|
||||
|
||||
result := make([]NetworkInterfaceInfo, 0, len(interfaces))
|
||||
for _, iface := range interfaces {
|
||||
// Skip loopback and down interfaces for multi-path networking
|
||||
if iface.Flags&net.FlagLoopback != 0 || iface.Flags&net.FlagUp == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
addrs, _ := iface.Addrs()
|
||||
addrStrings := make([]string, len(addrs))
|
||||
for i, addr := range addrs {
|
||||
addrStrings[i] = addr.String()
|
||||
}
|
||||
|
||||
result = append(result, NetworkInterfaceInfo{
|
||||
Index: uint32(iface.Index),
|
||||
Name: iface.Name,
|
||||
Addresses: addrStrings,
|
||||
MTU: iface.MTU,
|
||||
Flags: iface.Flags,
|
||||
})
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// NetworkInterfaceInfo represents information about a network interface
|
||||
type NetworkInterfaceInfo struct {
|
||||
Index uint32
|
||||
Name string
|
||||
Addresses []string
|
||||
MTU int
|
||||
Flags net.Flags
|
||||
}
|
||||
|
||||
// String returns a human-readable description of the interface
|
||||
func (nii NetworkInterfaceInfo) String() string {
|
||||
return fmt.Sprintf("Interface %s (index %d): MTU=%d, Addresses=%v, Flags=%v",
|
||||
nii.Name, nii.Index, nii.MTU, nii.Addresses, nii.Flags)
|
||||
}
|
||||
|
||||
// Example usage function
|
||||
func ExampleMultiPathUsage(logger *Logger) {
|
||||
// Print available interfaces
|
||||
interfaces, err := GetNetworkInterfaceInfo()
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to get interface info: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Verbosef("Available network interfaces:")
|
||||
for _, iface := range interfaces {
|
||||
logger.Verbosef(" %s", iface.String())
|
||||
}
|
||||
|
||||
// Example: Create multi-path device using specific interface names
|
||||
// This would send each packet through both eth0 and wlan0
|
||||
interfaceNames := []string{"eth0", "wlan0"}
|
||||
|
||||
// Note: You would need to create/configure your TUN device
|
||||
// tunDevice, err := tun.CreateTUN("wg0", 1420)
|
||||
// if err != nil {
|
||||
// logger.Errorf("Failed to create TUN: %v", err)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// device, err := NewMultiPathDeviceByNames(tunDevice, interfaceNames, logger)
|
||||
// if err != nil {
|
||||
// logger.Errorf("Failed to create multi-path device: %v", err)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// logger.Verbosef("Multi-path WireGuard device created successfully")
|
||||
}
|
||||
Reference in New Issue
Block a user