Files
basics/network/ipv6/ipv6_mask_darwin.go
2025-05-17 10:16:34 +00:00

105 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//go:build darwin
// +build darwin
package ipv6
import (
"fmt"
"os/exec"
"regexp"
"strconv"
"strings"
)
// macOS上获取前缀长度
func getPrefixFromIfconfig(interfaceName string) (string, error) {
cmd := exec.Command("ifconfig", interfaceName)
output, err := cmd.Output()
if err != nil {
return "", err
}
re := regexp.MustCompile(`inet6\s+([a-fA-F0-9:]+)%?\w*\s+prefixlen\s+(\d+)`)
matches := re.FindAllStringSubmatch(string(output), -1)
for _, match := range matches {
if len(match) < 3 {
continue
}
ipv6Addr := match[1]
prefixLen := match[2]
if strings.HasPrefix(ipv6Addr, "fe80") || // 链路本地地址
strings.HasPrefix(ipv6Addr, "::1") || // 回环地址
strings.HasPrefix(ipv6Addr, "fc") || // 本地唯一地址
strings.HasPrefix(ipv6Addr, "fd") || // 本地唯一地址
strings.HasPrefix(ipv6Addr, "ff") { // 组播地址
continue
}
prefixLenInt, err := strconv.Atoi(prefixLen)
if err != nil || prefixLenInt < 0 || prefixLenInt > 128 {
continue
}
return prefixLen, nil
}
return "", fmt.Errorf("未找到全局IPv6地址")
}
// macOS平台上使用networksetup命令获取更多信息
func getPrefixFromNetworksetup(interfaceName string) (string, error) {
cmd := exec.Command("networksetup", "-listallhardwareports")
output, err := cmd.Output()
if err != nil {
return "", err
}
lines := strings.Split(string(output), "\n")
var serviceName string
for i := 0; i < len(lines); i++ {
if strings.Contains(lines[i], "Device: "+interfaceName) && i > 0 {
serviceNameLine := lines[i-1]
if strings.HasPrefix(serviceNameLine, "Hardware Port: ") {
serviceName = strings.TrimPrefix(serviceNameLine, "Hardware Port: ")
break
}
}
}
if serviceName == "" {
return "", fmt.Errorf("未找到网络接口对应的服务名称")
}
cmd = exec.Command("networksetup", "-getinfo", serviceName)
output, err = cmd.Output()
if err != nil {
return "", err
}
re := regexp.MustCompile(`IPv6:\s*Automatic\s*\nIPv6\s*Address:\s*([a-fA-F0-9:]+)\s*\nIPv6\s*Prefix\s*Length:\s*(\d+)`)
match := re.FindStringSubmatch(string(output))
if len(match) >= 3 {
prefixLen := match[2]
prefixLenInt, err := strconv.Atoi(prefixLen)
if err != nil || prefixLenInt < 0 || prefixLenInt > 128 {
return "", fmt.Errorf("无效的IPv6前缀长度: %s", prefixLen)
}
return prefixLen, nil
}
return "", fmt.Errorf("未找到IPv6前缀长度信息")
}
// 获取 IPv6 子网掩码
func GetIPv6Mask(publicIPv6, language string) (string, error) {
if publicIPv6 == "" {
return "", fmt.Errorf("无公网IPV6地址")
}
interfaceName, err := getInterface()
if err != nil || interfaceName == "" {
return "", fmt.Errorf("获取网络接口失败: %v", err)
}
// 方法1从ifconfig获取前缀长度
prefixLen, err := getPrefixFromIfconfig(interfaceName)
if err == nil && prefixLen != "" {
return formatIPv6Mask(prefixLen, language), nil
}
// 方法2从networksetup获取前缀长度
prefixLen, err = getPrefixFromNetworksetup(interfaceName)
if err == nil && prefixLen != "" {
return formatIPv6Mask(prefixLen, language), nil
}
return formatIPv6Mask("128", language), nil
}