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  }