net/netmon: handle net.IPAddr types during interface address parsing (#17523)

updates tailscale/tailscale#16836

Android's altNetInterfaces implementation now returns net.IPAddr
types which netmon wasn't handling.

Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
This commit is contained in:
Jonathan Nobels 2025-10-10 12:34:27 -04:00 committed by GitHub
parent af15ee9c5f
commit 8e98ecb5f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 48 additions and 0 deletions

View File

@ -7,6 +7,7 @@ import (
"flag"
"net"
"net/netip"
"reflect"
"sync/atomic"
"testing"
"time"
@ -267,6 +268,45 @@ func TestIsMajorChangeFrom(t *testing.T) {
})
}
}
func TestForeachInterface(t *testing.T) {
tests := []struct {
name string
addrs []net.Addr
want []string
}{
{
name: "Mixed_IPv4_and_IPv6",
addrs: []net.Addr{
&net.IPNet{IP: net.IPv4(1, 2, 3, 4), Mask: net.CIDRMask(24, 32)},
&net.IPAddr{IP: net.IP{5, 6, 7, 8}, Zone: ""},
&net.IPNet{IP: net.ParseIP("2001:db8::1"), Mask: net.CIDRMask(64, 128)},
&net.IPAddr{IP: net.ParseIP("2001:db8::2"), Zone: ""},
},
want: []string{"1.2.3.4", "5.6.7.8", "2001:db8::1", "2001:db8::2"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var got []string
ifaces := InterfaceList{
{
Interface: &net.Interface{Name: "eth0"},
AltAddrs: tt.addrs,
},
}
ifaces.ForeachInterface(func(iface Interface, prefixes []netip.Prefix) {
for _, prefix := range prefixes {
ip := prefix.Addr()
got = append(got, ip.String())
}
})
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("got %q, want %q", got, tt.want)
}
})
}
}
type testOSMon struct {
osMon

View File

@ -183,6 +183,10 @@ func (ifaces InterfaceList) ForeachInterfaceAddress(fn func(Interface, netip.Pre
if pfx, ok := netaddr.FromStdIPNet(v); ok {
fn(iface, pfx)
}
case *net.IPAddr:
if ip, ok := netip.AddrFromSlice(v.IP); ok {
fn(iface, netip.PrefixFrom(ip, ip.BitLen()))
}
}
}
}
@ -215,6 +219,10 @@ func (ifaces InterfaceList) ForeachInterface(fn func(Interface, []netip.Prefix))
if pfx, ok := netaddr.FromStdIPNet(v); ok {
pfxs = append(pfxs, pfx)
}
case *net.IPAddr:
if ip, ok := netip.AddrFromSlice(v.IP); ok {
pfxs = append(pfxs, netip.PrefixFrom(ip, ip.BitLen()))
}
}
}
sort.Slice(pfxs, func(i, j int) bool {