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 }