github.com/sagernet/sing-box@v1.9.0-rc.20/transport/wireguard/device_system.go (about)

     1  package wireguard
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net"
     7  	"net/netip"
     8  	"os"
     9  
    10  	"github.com/sagernet/sing-box/adapter"
    11  	"github.com/sagernet/sing-box/common/dialer"
    12  	"github.com/sagernet/sing-box/option"
    13  	"github.com/sagernet/sing-tun"
    14  	"github.com/sagernet/sing/common"
    15  	E "github.com/sagernet/sing/common/exceptions"
    16  	M "github.com/sagernet/sing/common/metadata"
    17  	N "github.com/sagernet/sing/common/network"
    18  	wgTun "github.com/sagernet/wireguard-go/tun"
    19  )
    20  
    21  var _ Device = (*SystemDevice)(nil)
    22  
    23  type SystemDevice struct {
    24  	dialer      N.Dialer
    25  	device      tun.Tun
    26  	batchDevice tun.LinuxTUN
    27  	name        string
    28  	mtu         int
    29  	events      chan wgTun.Event
    30  	addr4       netip.Addr
    31  	addr6       netip.Addr
    32  }
    33  
    34  func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes []netip.Prefix, mtu uint32, gso bool) (*SystemDevice, error) {
    35  	var inet4Addresses []netip.Prefix
    36  	var inet6Addresses []netip.Prefix
    37  	for _, prefixes := range localPrefixes {
    38  		if prefixes.Addr().Is4() {
    39  			inet4Addresses = append(inet4Addresses, prefixes)
    40  		} else {
    41  			inet6Addresses = append(inet6Addresses, prefixes)
    42  		}
    43  	}
    44  	if interfaceName == "" {
    45  		interfaceName = tun.CalculateInterfaceName("wg")
    46  	}
    47  	tunInterface, err := tun.New(tun.Options{
    48  		Name:         interfaceName,
    49  		Inet4Address: inet4Addresses,
    50  		Inet6Address: inet6Addresses,
    51  		MTU:          mtu,
    52  		GSO:          gso,
    53  	})
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  	var inet4Address netip.Addr
    58  	var inet6Address netip.Addr
    59  	if len(inet4Addresses) > 0 {
    60  		inet4Address = inet4Addresses[0].Addr()
    61  	}
    62  	if len(inet6Addresses) > 0 {
    63  		inet6Address = inet6Addresses[0].Addr()
    64  	}
    65  	var batchDevice tun.LinuxTUN
    66  	if gso {
    67  		batchTUN, isBatchTUN := tunInterface.(tun.LinuxTUN)
    68  		if !isBatchTUN {
    69  			return nil, E.New("GSO is not supported on current platform")
    70  		}
    71  		batchDevice = batchTUN
    72  	}
    73  	return &SystemDevice{
    74  		dialer: common.Must1(dialer.NewDefault(router, option.DialerOptions{
    75  			BindInterface: interfaceName,
    76  		})),
    77  		device:      tunInterface,
    78  		batchDevice: batchDevice,
    79  		name:        interfaceName,
    80  		mtu:         int(mtu),
    81  		events:      make(chan wgTun.Event),
    82  		addr4:       inet4Address,
    83  		addr6:       inet6Address,
    84  	}, nil
    85  }
    86  
    87  func (w *SystemDevice) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
    88  	return w.dialer.DialContext(ctx, network, destination)
    89  }
    90  
    91  func (w *SystemDevice) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
    92  	return w.dialer.ListenPacket(ctx, destination)
    93  }
    94  
    95  func (w *SystemDevice) Inet4Address() netip.Addr {
    96  	return w.addr4
    97  }
    98  
    99  func (w *SystemDevice) Inet6Address() netip.Addr {
   100  	return w.addr6
   101  }
   102  
   103  func (w *SystemDevice) Start() error {
   104  	w.events <- wgTun.EventUp
   105  	return nil
   106  }
   107  
   108  func (w *SystemDevice) File() *os.File {
   109  	return nil
   110  }
   111  
   112  func (w *SystemDevice) Read(bufs [][]byte, sizes []int, offset int) (count int, err error) {
   113  	if w.batchDevice != nil {
   114  		count, err = w.batchDevice.BatchRead(bufs, offset, sizes)
   115  	} else {
   116  		sizes[0], err = w.device.Read(bufs[0][offset:])
   117  		if err == nil {
   118  			count = 1
   119  		} else if errors.Is(err, tun.ErrTooManySegments) {
   120  			err = wgTun.ErrTooManySegments
   121  		}
   122  	}
   123  	return
   124  }
   125  
   126  func (w *SystemDevice) Write(bufs [][]byte, offset int) (count int, err error) {
   127  	if w.batchDevice != nil {
   128  		return 0, w.batchDevice.BatchWrite(bufs, offset)
   129  	} else {
   130  		for _, b := range bufs {
   131  			_, err = w.device.Write(b[offset:])
   132  			if err != nil {
   133  				return
   134  			}
   135  		}
   136  	}
   137  	// WireGuard will not read count
   138  	return
   139  }
   140  
   141  func (w *SystemDevice) Flush() error {
   142  	return nil
   143  }
   144  
   145  func (w *SystemDevice) MTU() (int, error) {
   146  	return w.mtu, nil
   147  }
   148  
   149  func (w *SystemDevice) Name() (string, error) {
   150  	return w.name, nil
   151  }
   152  
   153  func (w *SystemDevice) Events() <-chan wgTun.Event {
   154  	return w.events
   155  }
   156  
   157  func (w *SystemDevice) Close() error {
   158  	return w.device.Close()
   159  }
   160  
   161  func (w *SystemDevice) BatchSize() int {
   162  	if w.batchDevice != nil {
   163  		return w.batchDevice.BatchSize()
   164  	}
   165  	return 1
   166  }