Description
- I have looked at the documentation here first?
- I have looked at the examples provided that may showcase my question here?
Package version eg. v9, v10:
v10.14.0
Issue, Question or Enhancement:
Unable to verify the IPv4 mapped IPv6 address
Code sample, to showcase or reproduce:
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
func main() {
v := validator.New()
// fail
err := v.Var("::ffff:c0a8:0101", "ipv6")
if err != nil {
fmt.Println(err)
}
// fail
err = v.Var("::ffff:192.168.1.1", "ipv6")
if err != nil {
fmt.Println(err)
}
// fail
err = v.Var("::ffff:c0a8:0101", "ip6_addr")
if err != nil {
fmt.Println(err)
}
// fail
err = v.Var("::ffff:192.168.1.1", "ip6_addr")
if err != nil {
fmt.Println(err)
}
}
Key: '' Error:Field validation for '' failed on the 'ipv6' tag
Key: '' Error:Field validation for '' failed on the 'ipv6' tag
Key: '' Error:Field validation for '' failed on the 'ip6_addr' tag
Key: '' Error:Field validation for '' failed on the 'ip6_addr' tag
I checked the source code, for ipv6
tag the root cause is when we check a valid ip is IPv4 or IPv6, we used the To4() function in net package:
// isIPv6 is the validation function for validating if the field's value is a valid v6 IP address.
func isIPv6(fl FieldLevel) bool {
ip := net.ParseIP(fl.Field().String())
return ip != nil && ip.To4() == nil
}
but in net package, it automatically covert the IPv4 mapped IPv6 address to IPv4, so the To4() function return value will not be nil, which make the isIPv6
return false. But I think this is not expected.
func (ip IP) To4() IP {
if len(ip) == IPv4len {
return ip
}
// covert the IPv4 mapped IPv6 address to IPv4 such as ::ffff:192.168.1.1 to 192.168.1.1
if len(ip) == IPv6len &&
isZeros(ip[0:10]) &&
ip[10] == 0xff &&
ip[11] == 0xff {
return ip[12:16]
}
return nil
}
we can simply fix this by check the raw ip string's format, for ipv4 it only can contains ".", for ipv6 it must contains ":" and it can optional contains "."(dot is for IPv4 mapped IPv6 address) but cannot only contains ".".
and corresponding issue also happens in ipv4
tag and ip4_addr
tag, the the IPv4 mapped IPv6 address can successfully pass by the ipv4 validation.
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
func main() {
v := validator.New()
// pass
err := v.Var("::ffff:c0a8:0101", "ipv4")
if err != nil {
fmt.Println(err)
}
// pass
err = v.Var("::ffff:192.168.1.1", "ipv4")
if err != nil {
fmt.Println(err)
}
// pass
err = v.Var("::ffff:c0a8:0101", "ip4_addr")
if err != nil {
fmt.Println(err)
}
// pass
err = v.Var("::ffff:192.168.1.1", "ip4_addr")
if err != nil {
fmt.Println(err)
}
}
submit a pull request to simply fix this: #1312 please review it,
Please take care of this, thanks.