Add windows support

This commit is contained in:
世界 2022-07-13 18:59:09 +08:00
parent 4f7247190c
commit 6c2c28da9d
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
54 changed files with 7023 additions and 191 deletions

View file

@ -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)...)
}