mirror of
				https://github.com/bjdgyc/anylink.git
				synced 2025-11-04 19:16:22 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			138 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package handler
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"net"
 | 
						|
	"os"
 | 
						|
	"strings"
 | 
						|
	"syscall"
 | 
						|
	"unsafe"
 | 
						|
 | 
						|
	"github.com/bjdgyc/anylink/base"
 | 
						|
	"github.com/bjdgyc/anylink/pkg/utils"
 | 
						|
	"github.com/bjdgyc/anylink/sessdata"
 | 
						|
)
 | 
						|
 | 
						|
// link vtap
 | 
						|
const vTapPrefix = "lvtap"
 | 
						|
 | 
						|
type Vtap struct {
 | 
						|
	*os.File
 | 
						|
	ifName string
 | 
						|
}
 | 
						|
 | 
						|
func (v *Vtap) Close() error {
 | 
						|
	v.File.Close()
 | 
						|
	cmdstr := fmt.Sprintf("ip link del %s", v.ifName)
 | 
						|
	return execCmd([]string{cmdstr})
 | 
						|
}
 | 
						|
 | 
						|
func checkMacvtap() {
 | 
						|
	_setGateway()
 | 
						|
	_checkTapIp(base.Cfg.Ipv4Master)
 | 
						|
 | 
						|
	ifName := "anylinkMacvtap"
 | 
						|
	// 加载 macvtap
 | 
						|
	cmdstr0 := fmt.Sprintf("modprobe -i macvtap")
 | 
						|
	// 开启主网卡混杂模式
 | 
						|
	cmdstr1 := fmt.Sprintf("ip link set dev %s promisc on", base.Cfg.Ipv4Master)
 | 
						|
	// 测试 macvtap 功能
 | 
						|
	cmdstr2 := fmt.Sprintf("ip link add link %s name %s type macvtap mode bridge", base.Cfg.Ipv4Master, ifName)
 | 
						|
	cmdstr3 := fmt.Sprintf("ip link del %s", ifName)
 | 
						|
	err := execCmd([]string{cmdstr0, cmdstr1, cmdstr2, cmdstr3})
 | 
						|
	if err != nil {
 | 
						|
		base.Fatal(err)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// 创建 Macvtap 网卡
 | 
						|
func LinkMacvtap(cSess *sessdata.ConnSession) error {
 | 
						|
	capL := sessdata.IpPool.IpLongMax - sessdata.IpPool.IpLongMin
 | 
						|
	ipN := utils.Ip2long(cSess.IpAddr) % capL
 | 
						|
	ifName := fmt.Sprintf("%s%d", vTapPrefix, ipN)
 | 
						|
 | 
						|
	cSess.SetIfName(ifName)
 | 
						|
 | 
						|
	cmdstr1 := fmt.Sprintf("ip link add link %s name %s type macvtap mode bridge", base.Cfg.Ipv4Master, ifName)
 | 
						|
	cmdstr2 := fmt.Sprintf("ip link set dev %s up mtu %d address %s", ifName, cSess.Mtu, cSess.MacHw)
 | 
						|
	err := execCmd([]string{cmdstr1, cmdstr2})
 | 
						|
	if err != nil {
 | 
						|
		base.Error(err)
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	cmdstr3 := fmt.Sprintf("sysctl -w net.ipv6.conf.%s.disable_ipv6=1", ifName)
 | 
						|
	execCmd([]string{cmdstr3})
 | 
						|
 | 
						|
	return createVtap(cSess, ifName)
 | 
						|
}
 | 
						|
 | 
						|
func checkIpvtap() {
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
// 创建 Ipvtap 网卡
 | 
						|
func LinkIpvtap(cSess *sessdata.ConnSession) error {
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
type ifReq struct {
 | 
						|
	Name  [0x10]byte
 | 
						|
	Flags uint16
 | 
						|
	pad   [0x28 - 0x10 - 2]byte
 | 
						|
}
 | 
						|
 | 
						|
func createVtap(cSess *sessdata.ConnSession, ifName string) error {
 | 
						|
	// 初始化 ifName
 | 
						|
	inf, err := net.InterfaceByName(ifName)
 | 
						|
	if err != nil {
 | 
						|
		base.Error(err)
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	tName := fmt.Sprintf("/dev/tap%d", inf.Index)
 | 
						|
 | 
						|
	var fdInt int
 | 
						|
 | 
						|
	fdInt, err = syscall.Open(tName, syscall.O_RDWR|syscall.O_NONBLOCK, 0)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	var flags uint16 = syscall.IFF_TAP | syscall.IFF_NO_PI
 | 
						|
	var req ifReq
 | 
						|
	req.Flags = flags
 | 
						|
 | 
						|
	_, _, errno := syscall.Syscall(
 | 
						|
		syscall.SYS_IOCTL,
 | 
						|
		uintptr(fdInt),
 | 
						|
		uintptr(syscall.TUNSETIFF),
 | 
						|
		uintptr(unsafe.Pointer(&req)),
 | 
						|
	)
 | 
						|
	if errno != 0 {
 | 
						|
		return os.NewSyscallError("ioctl", errno)
 | 
						|
	}
 | 
						|
 | 
						|
	file := os.NewFile(uintptr(fdInt), tName)
 | 
						|
	ifce := &Vtap{file, ifName}
 | 
						|
 | 
						|
	go allTapRead(ifce, cSess)
 | 
						|
	go allTapWrite(ifce, cSess)
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// 销毁未关闭的vtap
 | 
						|
func destroyVtap() {
 | 
						|
	its, err := net.Interfaces()
 | 
						|
	if err != nil {
 | 
						|
		base.Error(err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	for _, v := range its {
 | 
						|
		if strings.HasPrefix(v.Name, vTapPrefix) {
 | 
						|
			// 删除原来的网卡
 | 
						|
			cmdstr := fmt.Sprintf("ip link del %s", v.Name)
 | 
						|
			execCmd([]string{cmdstr})
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |