mirror of
https://github.com/SagerNet/sing-tun.git
synced 2025-04-03 20:07:40 +03:00
Add windows support
This commit is contained in:
parent
4f7247190c
commit
6c2c28da9d
54 changed files with 7023 additions and 191 deletions
99
tun_linux.go
99
tun_linux.go
|
@ -1,44 +1,72 @@
|
|||
package tun
|
||||
|
||||
import (
|
||||
"math"
|
||||
"net"
|
||||
"net/netip"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/tun"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
)
|
||||
|
||||
func Open(name string) (uintptr, error) {
|
||||
tunFd, err := tun.Open(name)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uintptr(tunFd), nil
|
||||
type NativeTun struct {
|
||||
name string
|
||||
inet4Address netip.Prefix
|
||||
inet6Address netip.Prefix
|
||||
mtu uint32
|
||||
autoRoute bool
|
||||
fdList []int
|
||||
}
|
||||
|
||||
func Configure(name string, inet4Address netip.Prefix, inet6Address netip.Prefix, mtu uint32, autoRoute bool) error {
|
||||
tunLink, err := netlink.LinkByName(name)
|
||||
func Open(name string, inet4Address netip.Prefix, inet6Address netip.Prefix, mtu uint32, autoRoute bool) (Tun, error) {
|
||||
tunFd, err := tun.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nativeTun := &NativeTun{
|
||||
name: name,
|
||||
fdList: []int{tunFd},
|
||||
mtu: mtu,
|
||||
inet4Address: inet4Address,
|
||||
inet6Address: inet6Address,
|
||||
autoRoute: autoRoute,
|
||||
}
|
||||
err = nativeTun.configure()
|
||||
if err != nil {
|
||||
return nil, E.Errors(err, syscall.Close(tunFd))
|
||||
}
|
||||
return nativeTun, nil
|
||||
}
|
||||
|
||||
func (t *NativeTun) configure() error {
|
||||
tunLink, err := netlink.LinkByName(t.name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if inet4Address.IsValid() {
|
||||
addr4, _ := netlink.ParseAddr(inet4Address.String())
|
||||
if t.inet4Address.IsValid() {
|
||||
addr4, _ := netlink.ParseAddr(t.inet4Address.String())
|
||||
err = netlink.AddrAdd(tunLink, addr4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if inet6Address.IsValid() {
|
||||
addr6, _ := netlink.ParseAddr(inet6Address.String())
|
||||
if t.inet6Address.IsValid() {
|
||||
addr6, _ := netlink.ParseAddr(t.inet6Address.String())
|
||||
err = netlink.AddrAdd(tunLink, addr6)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = netlink.LinkSetMTU(tunLink, int(mtu))
|
||||
err = netlink.LinkSetMTU(tunLink, int(t.mtu))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -48,8 +76,8 @@ func Configure(name string, inet4Address netip.Prefix, inet6Address netip.Prefix
|
|||
return err
|
||||
}
|
||||
|
||||
if autoRoute {
|
||||
if inet4Address.IsValid() {
|
||||
if t.autoRoute {
|
||||
if t.inet4Address.IsValid() {
|
||||
err = netlink.RouteAdd(&netlink.Route{
|
||||
Dst: &net.IPNet{
|
||||
IP: net.IPv4zero,
|
||||
|
@ -61,7 +89,7 @@ func Configure(name string, inet4Address netip.Prefix, inet6Address netip.Prefix
|
|||
return err
|
||||
}
|
||||
}
|
||||
if inet6Address.IsValid() {
|
||||
if t.inet6Address.IsValid() {
|
||||
err = netlink.RouteAdd(&netlink.Route{
|
||||
Dst: &net.IPNet{
|
||||
IP: net.IPv6zero,
|
||||
|
@ -74,17 +102,38 @@ func Configure(name string, inet4Address netip.Prefix, inet6Address netip.Prefix
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func UnConfigure(name string, inet4Address netip.Prefix, inet6Address netip.Prefix, autoRoute bool) error {
|
||||
if autoRoute {
|
||||
tunLink, err := netlink.LinkByName(name)
|
||||
func (t *NativeTun) NewEndpoint() (stack.LinkEndpoint, error) {
|
||||
var packetDispatchMode fdbased.PacketDispatchMode
|
||||
if runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" {
|
||||
packetDispatchMode = fdbased.PacketMMap
|
||||
} else {
|
||||
packetDispatchMode = fdbased.RecvMMsg
|
||||
}
|
||||
dupFdSize := int(math.Max(float64(runtime.NumCPU()/2), 1)) - 1
|
||||
for i := 0; i < dupFdSize; i++ {
|
||||
dupFd, err := syscall.Dup(t.fdList[0])
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
if inet4Address.IsValid() {
|
||||
t.fdList = append(t.fdList, dupFd)
|
||||
}
|
||||
return fdbased.New(&fdbased.Options{
|
||||
FDs: t.fdList,
|
||||
MTU: t.mtu,
|
||||
PacketDispatchMode: packetDispatchMode,
|
||||
})
|
||||
}
|
||||
|
||||
func (t *NativeTun) Close() error {
|
||||
tunLink, err := netlink.LinkByName(t.name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if t.autoRoute {
|
||||
if t.inet4Address.IsValid() {
|
||||
err = netlink.RouteDel(&netlink.Route{
|
||||
Dst: &net.IPNet{
|
||||
IP: net.IPv4zero,
|
||||
|
@ -96,7 +145,7 @@ func UnConfigure(name string, inet4Address netip.Prefix, inet6Address netip.Pref
|
|||
return err
|
||||
}
|
||||
}
|
||||
if inet6Address.IsValid() {
|
||||
if t.inet6Address.IsValid() {
|
||||
err = netlink.RouteDel(&netlink.Route{
|
||||
Dst: &net.IPNet{
|
||||
IP: net.IPv6zero,
|
||||
|
@ -109,5 +158,5 @@ func UnConfigure(name string, inet4Address netip.Prefix, inet6Address netip.Pref
|
|||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return E.Errors(common.Map(t.fdList, syscall.Close)...)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue