From b8058665b246824456e3b44c1f824cb2c6509424 Mon Sep 17 00:00:00 2001 From: Joseph Lee Date: Wed, 6 Dec 2023 18:13:29 +0900 Subject: [PATCH] feat: support ipv6 link-local address for mdns --- p2p/discovery/mdns/mdns.go | 40 +++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/p2p/discovery/mdns/mdns.go b/p2p/discovery/mdns/mdns.go index 637fcdcb08..dbd4b8aa13 100644 --- a/p2p/discovery/mdns/mdns.go +++ b/p2p/discovery/mdns/mdns.go @@ -5,6 +5,7 @@ import ( "errors" "io" "math/rand" + "net" "strings" "sync" @@ -124,6 +125,10 @@ func (s *mdnsService) startServer() error { var txts []string for _, addr := range addrs { if manet.IsThinWaist(addr) { // don't announce circuit addresses + if manet.IsIP6LinkLocal(addr) { + _, addr = ma.SplitFirst(addr) + } + txts = append(txts, dnsaddrPrefix+addr.String()) } } @@ -159,21 +164,26 @@ func (s *mdnsService) startResolver(ctx context.Context) { // We only care about the TXT records. // Ignore A, AAAA and PTR. addrs := make([]ma.Multiaddr, 0, len(entry.Text)) // assume that all TXT records are dnsaddrs - for _, s := range entry.Text { - if !strings.HasPrefix(s, dnsaddrPrefix) { + for _, txt := range entry.Text { + if !strings.HasPrefix(txt, dnsaddrPrefix) { log.Debug("missing dnsaddr prefix") continue } - addr, err := ma.NewMultiaddr(s[len(dnsaddrPrefix):]) + addr, err := ma.NewMultiaddr(txt[len(dnsaddrPrefix):]) if err != nil { - log.Debugf("failed to parse multiaddr: %s", err) + log.Debugf("failed to parse multiaddr: %txt", err) continue } + if manet.IsIP6LinkLocal(addr) { + ifaces, _ := net.Interfaces() + addr = s.fixIP6LinkLocalAddress(entry.ReceivedIfIndex, entry.ReceivedSrc, addr) + _ = ifaces + } addrs = append(addrs, addr) } infos, err := peer.AddrInfosFromP2pAddrs(addrs...) if err != nil { - log.Debugf("failed to get peer info: %s", err) + log.Debugf("failed to get peer info: %txt", err) continue } for _, info := range infos { @@ -192,6 +202,26 @@ func (s *mdnsService) startResolver(ctx context.Context) { }() } +func (s *mdnsService) fixIP6LinkLocalAddress(ifIndex int, src net.Addr, addr ma.Multiaddr) ma.Multiaddr { + var ifName string + udpAddr, ok := src.(*net.UDPAddr) + if ok && len(udpAddr.Zone) > 0 { + ifName = udpAddr.Zone + } else if ifIndex > 0 { + iface, err := net.InterfaceByIndex(ifIndex) + if err == nil { + ifName = iface.Name + } + } + if len(ifName) > 0 { + prefix, err := ma.NewMultiaddr("/ip6zone/" + ifName) + if err == nil { + return prefix.Encapsulate(addr) + } + } + return addr +} + func randomString(l int) string { const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789" s := make([]byte, 0, l)