Files
goodlink/netstack/setup_linux.go
T

111 lines
3.7 KiB
Go

//go:build linux
package netstack
import (
"fmt"
"log"
"net"
"os/exec"
"unsafe"
"golang.org/x/sys/unix"
)
func setUnixIP(name string, ip net.IP, mask net.IPMask) error {
log.Printf("setUnixIP: %s %s %s", name, ip, mask)
// 新增接口存在性检查
if err := checkInterfaceExists(name); err != nil {
return err
}
// 修改标志位设置流程(先关闭再开启)
ifreq, _ := unix.NewIfreq(name)
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCGIFFLAGS, uintptr(unsafe.Pointer(ifreq)))
if errno != 0 {
return fmt.Errorf("SIOCGIFFLAGS(pre-check) failed: %s", unix.ErrnoName(errno))
}
originalFlags := ifreq.Uint16()
// 临时关闭接口(关键步骤)
ifreq.SetUint16(originalFlags &^ unix.IFF_UP)
_, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(ifreq)))
if errno != 0 {
return fmt.Errorf("SIOCSIFFLAGS(down) failed: %s", unix.ErrnoName(errno))
}
// 设置IP地址结构体(修复掩码处理)
addr, _ := unix.NewIfreq(name)
addr.SetInet4Addr(ip.To4())
_, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCSIFADDR, uintptr(unsafe.Pointer(addr)))
if errno != 0 {
return fmt.Errorf("SIOCSIFADDR failed: %s", unix.ErrnoName(errno)) // 显示具体错误名称
}
// 设置子网掩码(修复变量名错误)
maskAddr, _ := unix.NewIfreq(name)
maskAddr.SetInet4Addr(net.IP(mask).To4()) // 显式转换掩码类型
_, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCSIFNETMASK, uintptr(unsafe.Pointer(maskAddr)))
if errno != 0 {
return fmt.Errorf("SIOCSIFNETMASK failed: %s", unix.ErrnoName(errno))
}
// 修改接口激活逻辑(关键修复)
ifreq, _ = unix.NewIfreq(name)
ifreq.SetUint16((originalFlags | unix.IFF_UP) &^ unix.IFF_NOARP) // 保留原始标志位并添加UP标志
_, _, errno = unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(ifreq)))
if errno != 0 {
return fmt.Errorf("SIOCSIFFLAGS failed: %s", unix.ErrnoName(errno))
}
log.Printf("Configuration applied successfully")
return nil
}
// 新增辅助函数
func checkInterfaceExists(name string) error {
ifreq, _ := unix.NewIfreq(name)
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(unix.AF_INET), unix.SIOCGIFFLAGS, uintptr(unsafe.Pointer(ifreq)))
if errno != 0 {
return fmt.Errorf("interface %s not exists: %s", name, unix.ErrnoName(errno))
}
return nil
}
// CleanupOldAdapter 清理之前可能残留的虚拟网卡(Linux 平台暂不需要特殊处理)
func CleanupOldAdapter(name string) {
// Linux 平台 TUN 设备在进程退出时会自动清理
// 这里可以尝试删除可能残留的设备
cmd := exec.Command("ip", "link", "delete", name)
_ = cmd.Run() // 忽略错误,设备可能不存在
}
// 修改调用端错误处理
func SetTunIP(wintunEP *Device, ip string, mask int) error {
// ip addr add 192.17.0.1/32 dev Goodlink
// ip link set Goodlink up
// ip route add 192.17.19.1 dev Goodlink
// 设置网卡eth0的IP地址为192.168.1.10/24
cmd := exec.Command("ip", "addr", "add", "192.17.0.1/32", "dev", GetName())
if err := cmd.Run(); err != nil {
return err
}
cmd = exec.Command("ip", "link", "set", GetName(), "up")
if err := cmd.Run(); err != nil {
return err
}
cmd = exec.Command("ip", "route", "add", GetRemoteIP(), "dev", GetName())
if err := cmd.Run(); err != nil {
return err
}
/*if err := setUnixIP(GetName(), net.ParseIP(ip), net.CIDRMask(mask, 32)); err != nil {
return fmt.Errorf("setUnixIP failed: %w", err)
}*/
return nil
}