diff --git a/baked_in.go b/baked_in.go index abb5cfe04..b81d72eee 100644 --- a/baked_in.go +++ b/baked_in.go @@ -2798,8 +2798,38 @@ func isHostnameRFC952(fl FieldLevel) bool { return hostnameRegexRFC952().MatchString(fl.Field().String()) } +func isDottedDecimalIPv4(s string) bool { + labels := 1 + labelLen := 0 + + for _, c := range s { + switch { + case c == '.': + if labelLen == 0 { + return false + } + labels++ + labelLen = 0 + case c >= '0' && c <= '9': + labelLen++ + default: + return false + } + } + + return labels == 4 && labelLen > 0 +} + func isHostnameRFC1123(fl FieldLevel) bool { - return hostnameRegexRFC1123().MatchString(fl.Field().String()) + val := fl.Field().String() + if !hostnameRegexRFC1123().MatchString(val) { + return false + } + if isDottedDecimalIPv4(val) { + ip := net.ParseIP(val) + return ip != nil && ip.To4() != nil + } + return true } func isFQDN(fl FieldLevel) bool { diff --git a/validator_test.go b/validator_test.go index 00eba5949..7e9d464db 100644 --- a/validator_test.go +++ b/validator_test.go @@ -10677,6 +10677,13 @@ func TestHostnameRFC1123Validation(t *testing.T) { {"example.", false}, {"test_example", false}, {"192.168.0.1", true}, + {"0.0.0.0", true}, + {"255.255.255.255", true}, + {"277.168.0.1", false}, + {"192.168.0.256", false}, + {"192.168.0.a", true}, + {"123.456", true}, + {"1.2.3", true}, {"email@example.com", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, {"2001:cdba:0:0:0:0:3257:9652", false},