jeessy2/ddns-go · error

网卡 %s 没有可用的单播地址

Error message

网卡 %s 没有可用的单播地址

What it means

GetLocalAddrFromInterface found the interface and read its addresses, but none of them were a global unicast address, so there is no IP the library can use as the client's bind address. Only addresses passing net.IP.IsGlobalUnicast() (public/universe scope, not loopback, link-local, or multicast) are accepted. This error means 'interface <name> has no usable unicast address'.

Source

Thrown at util/http_client_util.go:112

	}
}

// GetLocalAddrFromInterface 根据网卡名称获取本地IP地址
func GetLocalAddrFromInterface(ifaceName string) (string, error) {
	iface, err := net.InterfaceByName(ifaceName)
	if err != nil {
		return "", fmt.Errorf("找不到网卡 %s: %v", ifaceName, err)
	}
	addrs, err := iface.Addrs()
	if err != nil {
		return "", fmt.Errorf("获取网卡 %s 地址失败: %v", ifaceName, err)
	}
	for _, addr := range addrs {
		if ipNet, ok := addr.(*net.IPNet); ok && ipNet.IP.IsGlobalUnicast() {
			return ipNet.IP.String(), nil
		}
	}
	return "", fmt.Errorf("网卡 %s 没有可用的单播地址", ifaceName)
}

// CreateHTTPClientWithInterface 创建绑定指定网卡的HTTP客户端
func CreateHTTPClientWithInterface(ifaceName string) *http.Client {
	if ifaceName == "" {
		return CreateHTTPClient()
	}
	localIP, err := GetLocalAddrFromInterface(ifaceName)
	if err != nil {
		Log("绑定网卡失败, 将使用默认网卡. 网卡: %s, 错误: %v", ifaceName, err)
		return CreateHTTPClient()
	}
	localAddr := &net.TCPAddr{IP: net.ParseIP(localIP)}
	boundDialer := newHTTPDialer(localAddr)
	setLinuxBindToDevice(boundDialer, ifaceName)
	transport := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {

View on GitHub (pinned to 5874c2e666)

Solutions

  1. Check `ip addr show <iface>` — the interface needs a global-scope address; fix DHCP or assign a static address
  2. Select a different interface that has a real (global unicast) IP address
  3. Wait for DHCP/SLAAC to complete before initializing the client, or re-trigger the DHCP request
  4. If you intentionally bind to a link address, this API cannot help — remove the interface binding and use the default client

Example fix

// before
client := util.CreateHTTPClientWithInterface("eth1") // eth1 only has 169.254.10.20 (APIPA)
// after
dhclient eth1 # or assign a static global address, then:
client := util.CreateHTTPClientWithInterface("eth1")
Defensive patterns

Strategy: validation

Validate before calling

func ifaceHasUsableAddr(name string) bool {
	iface, err := net.InterfaceByName(name)
	if err != nil { return false }
	addrs, _ := iface.Addrs()
	for _, a := range addrs {
		if ipnet, ok := a.(*net.IPNet); ok && ipnet.IP.IsGlobalUnicast() { return true }
	}
	return false
}
// guard: if !ifaceHasUsableAddr(cfg.Interface) { alert/fix network first }

Try / catch

_, err := util.GetLocalAddrFromInterface(ifaceName)
if err != nil {
	log.Printf("interface %s has no global unicast address (%v); using default client", ifaceName, err)
	client = util.CreateHTTPClient()
}

Prevention

When it happens

Trigger: Calling GetLocalAddrFromInterface/CreateHTTPClientWithInterface on an interface whose only addresses are loopback (127.0.0.1/::1), link-local (169.254.x.x, fe80::/10), or multicast-only — e.g. an interface that is UP but never got a DHCP lease.

Common situations: DHCP failure leaving only an APIPA 169.254.x.x address on the NIC; freshly created veth/bridge with no IP; VPN tun device up but unconfigured; point-to-point links with only link-local addressing.

Related errors


AI-assisted analysis of jeessy2/ddns-go@5874c2e666 (2026-09-03). Data as JSON: /api/errors/d40561f70dda8bbc. Report an issue: GitHub.