github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/netlink/route_linux.go (about) 1 //go:build !android 2 // +build !android 3 4 package netlink 5 6 import ( 7 "fmt" 8 "net" 9 "syscall" 10 "unsafe" 11 12 "github.com/Asutorufa/yuhaiin/pkg/log" 13 "github.com/vishvananda/netlink" 14 "golang.org/x/sys/unix" 15 ) 16 17 func Route(opt *Options) error { 18 if opt.Interface.Scheme != "tun" { 19 return nil 20 } 21 22 link, err := netlink.LinkByName(opt.Interface.Name) 23 if err != nil { 24 return err 25 } 26 27 err = netlink.LinkSetMTU(link, opt.MTU) 28 if err != nil { 29 return fmt.Errorf("unable to set MTU: %w", err) 30 } 31 32 for _, address := range append(opt.Inet4Address, opt.Inet6Address...) { 33 addr, err := netlink.ParseAddr(address.String()) 34 if err != nil { 35 continue 36 } 37 38 err = netlink.AddrAdd(link, addr) 39 if err != nil { 40 return fmt.Errorf("unable to add address: %w", err) 41 } 42 } 43 44 if err = netlink.LinkSetUp(link); err != nil { 45 return fmt.Errorf("unable to set link up: %w", err) 46 } 47 48 var tableIndex int = 63 49 // for { 50 // tableIndex = int(rand.Uint32()) 51 // routeList, fErr := netlink.RouteListFiltered(netlink.FAMILY_ALL, &netlink.Route{Table: tableIndex}, netlink.RT_FILTER_TABLE) 52 // if len(routeList) == 0 || fErr != nil { 53 // break 54 // } 55 // } 56 57 for _, route := range opt.Routes { 58 r := netlink.Route{ 59 Dst: &net.IPNet{ 60 IP: route.Masked().Addr().AsSlice(), 61 Mask: net.CIDRMask(route.Bits(), route.Addr().BitLen()), 62 }, 63 LinkIndex: link.Attrs().Index, 64 Table: int(tableIndex), 65 } 66 err = netlink.RouteAdd(&r) 67 if err != nil { 68 log.Error("add route error", "err", err) 69 } 70 } 71 72 // for _, address := range append(opt.Inet4Address, opt.Inet6Address...) { 73 // it := netlink.NewRule() 74 // it.Priority = 30001 75 // it.Dst = &net.IPNet{ 76 // IP: address.Addr().AsSlice(), 77 // Mask: net.CIDRMask(address.Bits(), address.Addr().BitLen()), 78 // } 79 // it.Table = int(tableIndex) 80 // it.Family = unix.AF_INET 81 // err = netlink.RuleAdd(it) 82 // if err != nil { 83 // return err 84 // } 85 // } 86 87 // it := netlink.NewRule() 88 // it.Priority = 30001 89 // it.Invert = true 90 // it.Dport = netlink.NewRulePortRange(53, 53) 91 // it.Table = unix.RT_TABLE_MAIN 92 // it.SuppressPrefixlen = 0 93 // it.Family = unix.AF_INET 94 // err = netlink.RuleAdd(it) 95 // if err != nil { 96 // return err 97 // } 98 99 if len(opt.Routes) > 0 { 100 if len(opt.Inet4Address) > 0 { 101 it := netlink.NewRule() 102 it.Priority = 30001 103 it.Table = int(tableIndex) 104 it.Family = unix.AF_INET 105 err = netlink.RuleAdd(it) 106 if err != nil { 107 log.Error("unable to add ipv4 rule", "err", err) 108 } 109 } 110 111 if len(opt.Inet6Address) > 0 { 112 it := netlink.NewRule() 113 it.Priority = 30002 114 it.Table = int(tableIndex) 115 it.Family = unix.AF_INET6 116 err = netlink.RuleAdd(it) 117 if err != nil { 118 log.Error("unable to add ipv6 rule", "err", err) 119 } 120 } 121 } 122 123 return nil 124 } 125 126 const ifReqSize = unix.IFNAMSIZ + 64 127 128 func getTunnelName(fd int32) (string, error) { 129 var ifr [ifReqSize]byte 130 var errno syscall.Errno 131 _, _, errno = unix.Syscall( 132 unix.SYS_IOCTL, 133 uintptr(fd), 134 uintptr(unix.TUNGETIFF), 135 uintptr(unsafe.Pointer(&ifr[0])), 136 ) 137 if errno != 0 { 138 return "", fmt.Errorf("failed to get name of TUN device: %w", errno) 139 } 140 return unix.ByteSliceToString(ifr[:]), nil 141 }