From 33a29c1f88bea8a7a1ac48756ec84cc07c2c95be Mon Sep 17 00:00:00 2001 From: hktalent <18223385+hktalent@users.noreply.github.com> Date: Sat, 17 Sep 2022 23:44:38 +0800 Subject: [PATCH 1/3] add IsPrivateIP By @hktalent --- validator.go | 38 ++++++++++++++++++++++++++++++++++++++ validator_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/validator.go b/validator.go index 46ecfc8..8fe8c0a 100644 --- a/validator.go +++ b/validator.go @@ -69,6 +69,44 @@ func IsEmail(str string) bool { return rxEmail.MatchString(str) } +// private ip lists +var aPrivateIP []*net.IPNet + +// IsPrivateIP check if the string is an private IP +func IsPrivateIP(ip string) bool { + if 0 == len(aPrivateIP) { + for _, cidr := range []string{ + "127.0.0.0/8", // IPv4 loopback + "10.0.0.0/8", // RFC1918 + "172.16.0.0/12", // RFC1918 + "192.168.0.0/16", // RFC1918 + "169.254.0.0/16", // RFC3927 link-local + "::1/128", // IPv6 loopback + "fe80::/10", // IPv6 link-local + "fc00::/7", // IPv6 unique local addr + } { + _, block, err := net.ParseCIDR(cidr) + if err != nil { + continue + } + aPrivateIP = append(aPrivateIP, block) + } + } + oIp := net.ParseIP(ip) + if oIp == nil { + return false + } + if oIp.IsLoopback() || oIp.IsLinkLocalUnicast() || oIp.IsLinkLocalMulticast() { + return true + } + for _, s := range aPrivateIP { + if s.Contains(oIp) { + return true + } + } + return false +} + // IsExistingEmail checks if the string is an email of existing domain func IsExistingEmail(email string) bool { diff --git a/validator_test.go b/validator_test.go index bff8613..044587e 100644 --- a/validator_test.go +++ b/validator_test.go @@ -3865,3 +3865,30 @@ func TestIsE164(t *testing.T) { } } } + +func TestIsPrivateIP(t *testing.T) { + t.Parallel() + // Without version + var tests = []struct { + param string + expected bool + }{ + {"", false}, + {"127.0.0.1", true}, + {"127.0.2.1", true}, + {"172.16.0.19", true}, + {"fe80::b8:6771:9e7c:f6f1", true}, + {"ee80::b8:6771:9e7c:f6f1", false}, + {"fe80::1", true}, + {"192.168.10.1", true}, + {"::1", true}, + {"2001:db8:0000:1:1:1:1:1", false}, + {"300.0.0.0", false}, + } + for _, test := range tests { + actual := IsPrivateIP(test.param) + if actual != test.expected { + t.Errorf("Expected IsPrivateIP(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} From 554c02963a82e48625124d4e39e6a118ecdb3b3f Mon Sep 17 00:00:00 2001 From: hktalent <18223385+hktalent@users.noreply.github.com> Date: Sat, 17 Sep 2022 23:47:45 +0800 Subject: [PATCH 2/3] add IsPrivateIP doc By @hktalent --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2c3fc35..86effb0 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,7 @@ func IsHost(str string) bool func IsIP(str string) bool func IsIPv4(str string) bool func IsIPv6(str string) bool +func IsPrivateIP(ip string) bool func IsISBN(str string, version int) bool func IsISBN10(str string) bool func IsISBN13(str string) bool @@ -370,6 +371,7 @@ Here is a list of available validators for struct fields (validator - used funct "base64": IsBase64, "datauri": IsDataURI, "ip": IsIP, +"ip": IsPrivateIP "port": IsPort, "ipv4": IsIPv4, "ipv6": IsIPv6, From f354036af9a006b7305407ace47647a87ead3c3b Mon Sep 17 00:00:00 2001 From: hktalent <18223385+hktalent@users.noreply.github.com> Date: Sat, 17 Sep 2022 23:51:47 +0800 Subject: [PATCH 3/3] fix --- validator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validator.go b/validator.go index 8fe8c0a..cace32d 100644 --- a/validator.go +++ b/validator.go @@ -96,7 +96,7 @@ func IsPrivateIP(ip string) bool { if oIp == nil { return false } - if oIp.IsLoopback() || oIp.IsLinkLocalUnicast() || oIp.IsLinkLocalMulticast() { + if oIp.IsLoopback() || oIp.IsLinkLocalUnicast() || oIp.IsLinkLocalMulticast() || oIp.IsPrivate() { return true } for _, s := range aPrivateIP {