66 "net"
77 "net/netip"
88 "os"
9+ "sync"
910
1011 "github.com/sagernet/sing-box/adapter"
1112 "github.com/sagernet/sing-box/common/dialer"
@@ -21,14 +22,16 @@ import (
2122var _ Device = (* SystemDevice )(nil )
2223
2324type 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
25+ dialer N.Dialer
26+ device tun.Tun
27+ batchDevice tun.LinuxTUN
28+ name string
29+ mtu uint32
30+ inet4Addresses []netip.Prefix
31+ inet6Addresses []netip.Prefix
32+ gso bool
33+ events chan wgTun.Event
34+ closeOnce sync.Once
3235}
3336
3437func NewSystemDevice (router adapter.Router , interfaceName string , localPrefixes []netip.Prefix , mtu uint32 , gso bool ) (* SystemDevice , error ) {
@@ -44,43 +47,17 @@ func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes
4447 if interfaceName == "" {
4548 interfaceName = tun .CalculateInterfaceName ("wg" )
4649 }
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- }
50+
7351 return & SystemDevice {
7452 dialer : common .Must1 (dialer .NewDefault (router , option.DialerOptions {
7553 BindInterface : interfaceName ,
7654 })),
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 ,
55+ name : interfaceName ,
56+ mtu : mtu ,
57+ inet4Addresses : inet4Addresses ,
58+ inet6Addresses : inet6Addresses ,
59+ gso : gso ,
60+ events : make (chan wgTun.Event ),
8461 }, nil
8562}
8663
@@ -93,14 +70,39 @@ func (w *SystemDevice) ListenPacket(ctx context.Context, destination M.Socksaddr
9370}
9471
9572func (w * SystemDevice ) Inet4Address () netip.Addr {
96- return w .addr4
73+ if len (w .inet4Addresses ) == 0 {
74+ return netip.Addr {}
75+ }
76+ return w .inet4Addresses [0 ].Addr ()
9777}
9878
9979func (w * SystemDevice ) Inet6Address () netip.Addr {
100- return w .addr6
80+ if len (w .inet6Addresses ) == 0 {
81+ return netip.Addr {}
82+ }
83+ return w .inet6Addresses [0 ].Addr ()
10184}
10285
10386func (w * SystemDevice ) Start () error {
87+ tunInterface , err := tun .New (tun.Options {
88+ Name : w .name ,
89+ Inet4Address : w .inet4Addresses ,
90+ Inet6Address : w .inet6Addresses ,
91+ MTU : w .mtu ,
92+ GSO : w .gso ,
93+ })
94+ if err != nil {
95+ return err
96+ }
97+ w .device = tunInterface
98+ if w .gso {
99+ batchTUN , isBatchTUN := tunInterface .(tun.LinuxTUN )
100+ if ! isBatchTUN {
101+ tunInterface .Close ()
102+ return E .New ("GSO is not supported on current platform" )
103+ }
104+ w .batchDevice = batchTUN
105+ }
104106 w .events <- wgTun .EventUp
105107 return nil
106108}
@@ -143,7 +145,7 @@ func (w *SystemDevice) Flush() error {
143145}
144146
145147func (w * SystemDevice ) MTU () (int , error ) {
146- return w .mtu , nil
148+ return int ( w .mtu ) , nil
147149}
148150
149151func (w * SystemDevice ) Name () (string , error ) {
@@ -155,6 +157,7 @@ func (w *SystemDevice) Events() <-chan wgTun.Event {
155157}
156158
157159func (w * SystemDevice ) Close () error {
160+ close (w .events )
158161 return w .device .Close ()
159162}
160163
0 commit comments