diff --git a/src/mod/netutils/ipmatch.go b/src/mod/netutils/ipmatch.go index 942bf56..a0c65a1 100644 --- a/src/mod/netutils/ipmatch.go +++ b/src/mod/netutils/ipmatch.go @@ -108,14 +108,24 @@ func MatchIpCIDR(ip string, cidr string) bool { // Check if a ip is private IP range func IsPrivateIP(ipStr string) bool { if ipStr == "127.0.0.1" || ipStr == "::1" { - //local loopback + // local loopback return true } ip := net.ParseIP(ipStr) if ip == nil { return false } - return ip.IsPrivate() + if ip.IsPrivate() { + return true + } + // Check for IPv6 link-local addresses (fe80::/10) + if ip.To16() != nil && ip.To4() == nil { + // IPv6 only + if ip[0] == 0xfe && (ip[1]&0xc0) == 0x80 { + return true + } + } + return false } // Check if an Ip string is ipv6 diff --git a/src/mod/netutils/netutils_test.go b/src/mod/netutils/netutils_test.go index 118249d..0ba3eec 100644 --- a/src/mod/netutils/netutils_test.go +++ b/src/mod/netutils/netutils_test.go @@ -26,3 +26,56 @@ func TestHandlePing(t *testing.T) { t.Log(realIP, pingTime, ttl) } +func TestMatchIpWildcard_IPv6(t *testing.T) { + // IPv6 wildcards are not supported by MatchIpWildcard, so these should all return false + tests := []struct { + ip string + wildcard string + want bool + }{ + {"fd7a:115c:a1e0::e101:6f0f", "fd7a:115c:a1e0::e101:6f0f", false}, // not supported + {"fd7a:115c:a1e0::e101:6f0f", "*:*:*:*:*:*:*:*", false}, + } + for _, tt := range tests { + got := netutils.MatchIpWildcard(tt.ip, tt.wildcard) + if got != tt.want { + t.Errorf("MatchIpWildcard(%q, %q) = %v, want %v", tt.ip, tt.wildcard, got, tt.want) + } + } +} + +func TestMatchIpCIDR_IPv6(t *testing.T) { + tests := []struct { + ip string + cidr string + want bool + }{ + {"fd7a:115c:a1e0::e101:6f0f", "fd7a:115c:a1e0::/48", true}, + {"fd7a:115c:a1e0::e101:6f0f", "fd7a:115c:a1e0::/64", true}, + {"fd7a:115c:a1e0::e101:6f0f", "fd7a:115c:a1e1::/48", false}, + {"fd7a:115c:a1e0::e101:6f0f", "fd7a:115c:a1e0::/128", false}, + } + for _, tt := range tests { + got := netutils.MatchIpCIDR(tt.ip, tt.cidr) + if got != tt.want { + t.Errorf("MatchIpCIDR(%q, %q) = %v, want %v", tt.ip, tt.cidr, got, tt.want) + } + } +} + +func TestIsPrivateIP_IPv6(t *testing.T) { + tests := []struct { + ip string + want bool + }{ + {"fd7a:115c:a1e0::e101:6f0f", true}, // Unique local address (fc00::/7) + {"fe80::1", true}, // Link-local + {"2001:db8::1", false}, // Documentation address + } + for _, tt := range tests { + got := netutils.IsPrivateIP(tt.ip) + if got != tt.want { + t.Errorf("IsPrivateIP(%q) = %v, want %v", tt.ip, got, tt.want) + } + } +}