github.com/sagernet/sing-box@v1.2.7/experimental/libbox/service.go (about) 1 package libbox 2 3 import ( 4 "context" 5 "net/netip" 6 "syscall" 7 8 "github.com/sagernet/sing-box" 9 "github.com/sagernet/sing-box/adapter" 10 "github.com/sagernet/sing-box/common/process" 11 "github.com/sagernet/sing-box/experimental/libbox/internal/procfs" 12 "github.com/sagernet/sing-box/experimental/libbox/platform" 13 "github.com/sagernet/sing-box/option" 14 "github.com/sagernet/sing-tun" 15 "github.com/sagernet/sing/common" 16 "github.com/sagernet/sing/common/control" 17 E "github.com/sagernet/sing/common/exceptions" 18 N "github.com/sagernet/sing/common/network" 19 ) 20 21 type BoxService struct { 22 ctx context.Context 23 cancel context.CancelFunc 24 instance *box.Box 25 } 26 27 func NewService(configContent string, platformInterface PlatformInterface) (*BoxService, error) { 28 options, err := parseConfig(configContent) 29 if err != nil { 30 return nil, err 31 } 32 ctx, cancel := context.WithCancel(context.Background()) 33 instance, err := box.New(box.Options{ 34 Context: ctx, 35 Options: options, 36 PlatformInterface: &platformInterfaceWrapper{iif: platformInterface, useProcFS: platformInterface.UseProcFS()}, 37 }) 38 if err != nil { 39 cancel() 40 return nil, E.Cause(err, "create service") 41 } 42 return &BoxService{ 43 ctx: ctx, 44 cancel: cancel, 45 instance: instance, 46 }, nil 47 } 48 49 func (s *BoxService) Start() error { 50 return s.instance.Start() 51 } 52 53 func (s *BoxService) Close() error { 54 s.cancel() 55 return s.instance.Close() 56 } 57 58 var _ platform.Interface = (*platformInterfaceWrapper)(nil) 59 60 type platformInterfaceWrapper struct { 61 iif PlatformInterface 62 useProcFS bool 63 router adapter.Router 64 } 65 66 func (w *platformInterfaceWrapper) Initialize(ctx context.Context, router adapter.Router) error { 67 w.router = router 68 return nil 69 } 70 71 func (w *platformInterfaceWrapper) UsePlatformAutoDetectInterfaceControl() bool { 72 return w.iif.UsePlatformAutoDetectInterfaceControl() 73 } 74 75 func (w *platformInterfaceWrapper) AutoDetectInterfaceControl() control.Func { 76 return func(network, address string, conn syscall.RawConn) error { 77 return control.Raw(conn, func(fd uintptr) error { 78 return w.iif.AutoDetectInterfaceControl(int32(fd)) 79 }) 80 } 81 } 82 83 func (w *platformInterfaceWrapper) OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error) { 84 if len(options.IncludeUID) > 0 || len(options.ExcludeUID) > 0 { 85 return nil, E.New("android: unsupported uid options") 86 } 87 if len(options.IncludeAndroidUser) > 0 { 88 return nil, E.New("android: unsupported android_user option") 89 } 90 tunFd, err := w.iif.OpenTun(&tunOptions{options, platformOptions}) 91 if err != nil { 92 return nil, err 93 } 94 options.Name, err = getTunnelName(tunFd) 95 if err != nil { 96 return nil, E.Cause(err, "query tun name") 97 } 98 dupFd, err := dup(int(tunFd)) 99 if err != nil { 100 return nil, E.Cause(err, "dup tun file descriptor") 101 } 102 options.FileDescriptor = dupFd 103 return tun.New(*options) 104 } 105 106 func (w *platformInterfaceWrapper) Write(p []byte) (n int, err error) { 107 w.iif.WriteLog(string(p)) 108 return len(p), nil 109 } 110 111 func (w *platformInterfaceWrapper) FindProcessInfo(ctx context.Context, network string, source netip.AddrPort, destination netip.AddrPort) (*process.Info, error) { 112 var uid int32 113 if w.useProcFS { 114 uid = procfs.ResolveSocketByProcSearch(network, source, destination) 115 if uid == -1 { 116 return nil, E.New("procfs: not found") 117 } 118 } else { 119 var ipProtocol int32 120 switch N.NetworkName(network) { 121 case N.NetworkTCP: 122 ipProtocol = syscall.IPPROTO_TCP 123 case N.NetworkUDP: 124 ipProtocol = syscall.IPPROTO_UDP 125 default: 126 return nil, E.New("unknown network: ", network) 127 } 128 var err error 129 uid, err = w.iif.FindConnectionOwner(ipProtocol, source.Addr().String(), int32(source.Port()), destination.Addr().String(), int32(destination.Port())) 130 if err != nil { 131 return nil, err 132 } 133 } 134 packageName, _ := w.iif.PackageNameByUid(uid) 135 return &process.Info{UserId: uid, PackageName: packageName}, nil 136 } 137 138 func (w *platformInterfaceWrapper) UsePlatformDefaultInterfaceMonitor() bool { 139 return w.iif.UsePlatformDefaultInterfaceMonitor() 140 } 141 142 func (w *platformInterfaceWrapper) CreateDefaultInterfaceMonitor(errorHandler E.Handler) tun.DefaultInterfaceMonitor { 143 return &platformDefaultInterfaceMonitor{ 144 platformInterfaceWrapper: w, 145 errorHandler: errorHandler, 146 defaultInterfaceIndex: -1, 147 } 148 } 149 150 func (w *platformInterfaceWrapper) UsePlatformInterfaceGetter() bool { 151 return w.iif.UsePlatformInterfaceGetter() 152 } 153 154 func (w *platformInterfaceWrapper) Interfaces() ([]platform.NetworkInterface, error) { 155 interfaceIterator, err := w.iif.GetInterfaces() 156 if err != nil { 157 return nil, err 158 } 159 var interfaces []platform.NetworkInterface 160 for _, netInterface := range iteratorToArray[*NetworkInterface](interfaceIterator) { 161 interfaces = append(interfaces, platform.NetworkInterface{ 162 Index: int(netInterface.Index), 163 MTU: int(netInterface.MTU), 164 Name: netInterface.Name, 165 Addresses: common.Map(iteratorToArray[string](netInterface.Addresses), netip.MustParsePrefix), 166 }) 167 } 168 return interfaces, nil 169 }