Skip to content

Commit

Permalink
Prefer IPv6 over IPv4-in-IPv6
Browse files Browse the repository at this point in the history
  • Loading branch information
edaniels committed Mar 26, 2024
1 parent 78fee6f commit f429a35
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 5 deletions.
31 changes: 26 additions & 5 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -954,7 +954,7 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int
c.log.Warnf("[%s] no interface for %d", c.name, ifIndex)
return
}
var selectedAddr *netip.Addr
var selectedAddrs []netip.Addr
for _, addr := range ifc.ipAddrs {
addrCopy := addr

Expand All @@ -977,13 +977,34 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int
}
}

selectedAddr = &addrCopy
break
selectedAddrs = append(selectedAddrs, addrCopy)
}
if selectedAddr == nil {
if len(selectedAddrs) == 0 {
c.log.Debugf("[%s] failed to find suitable IP for interface %d; deriving address from source address c.name,instead", ifIndex)
} else {
localAddress = selectedAddr
// choose the best match
var choice *netip.Addr
for _, option := range selectedAddrs {
optCopy := option
if option.Is4() {
// select first
choice = &optCopy
break
}
// we're okay with 4In6 for now but ideally we get a an actual IPv6.
// Maybe in the future we never want this but it does look like Docker
// can route IPv4 over IPv6.
if choice == nil {
choice = &optCopy
} else if !optCopy.Is4In6() {
choice = &optCopy
}
if !optCopy.Is4In6() {
break
}
// otherwise keep searching for an actual IPv6
}
localAddress = choice
}
}
if ifIndex == -1 || localAddress == nil {
Expand Down
46 changes: 46 additions & 0 deletions conn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,52 @@ func TestValidCommunicationIPv46MixedLocalAddress(t *testing.T) {
}
}

func TestValidCommunicationIPv66Mixed(t *testing.T) {
if runtime.GOARCH == "386" {
t.Skip("IPv6 not supported on 386 for some reason")
}

lim := test.TimeOut(time.Second * 10)
defer lim.Stop()

report := test.CheckRoutines(t)
defer report()

aSock6 := createListener6(t)
bSock6 := createListener6(t)

aServer, err := Server(nil, ipv6.NewPacketConn(aSock6), &Config{
LocalNames: []string{"pion-mdns-1.local"},
})
check(err, t)

bServer, err := Server(nil, ipv6.NewPacketConn(bSock6), &Config{})
check(err, t)

header, addr, err := bServer.QueryAddr(context.TODO(), "pion-mdns-1.local")
check(err, t)
if header.Type != dnsmessage.TypeAAAA {
t.Fatalf("expected AAAA but got %s", header.Type)
}
if addr.String() == localAddress {
t.Fatalf("unexpected local address: %v", addr)
}
if addr.Is4In6() {
t.Fatalf("expected address to not be ipv4-to-ipv6 mapped: %v", addr)
}
checkIPv6(addr, t)

check(aServer.Close(), t)
check(bServer.Close(), t)

if len(aServer.queries) > 0 {
t.Fatalf("Queries not cleaned up after aServer close")
}
if len(bServer.queries) > 0 {
t.Fatalf("Queries not cleaned up after bServer close")
}
}

func TestValidCommunicationIPv66MixedLocalAddress(t *testing.T) {
if runtime.GOARCH == "386" {
t.Skip("IPv6 not supported on 386 for some reason")
Expand Down

0 comments on commit f429a35

Please sign in to comment.