summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoyalsoldier <[email protected]>2024-07-06 15:04:36 +0800
committerLoyalsoldier <[email protected]>2024-07-06 15:04:36 +0800
commit5843ee29c435b393bec57a367775c2f4e266eedc (patch)
tree7bbfde5a646c6f31f57418666b362038e8771c15
parent2c15c6946d02d63f9f94d23bc33b29941786564a (diff)
Fix: processing IPv4-mapped IPv6 address
-rw-r--r--lib/entry.go93
-rw-r--r--lib/error.go2
2 files changed, 70 insertions, 25 deletions
diff --git a/lib/entry.go b/lib/entry.go
index 7eecd14d..311e89cb 100644
--- a/lib/entry.go
+++ b/lib/entry.go
@@ -45,6 +45,7 @@ func (e *Entry) processPrefix(src any) (*netip.Prefix, IPType, error) {
if !ok {
return nil, "", ErrInvalidIP
}
+ ip = ip.Unmap()
switch {
case ip.Is4():
prefix := netip.PrefixFrom(ip, 32)
@@ -61,7 +62,7 @@ func (e *Entry) processPrefix(src any) (*netip.Prefix, IPType, error) {
if !ok {
return nil, "", ErrInvalidIPNet
}
- ip := prefix.Addr()
+ ip := prefix.Addr().Unmap()
switch {
case ip.Is4():
return &prefix, IPv4, nil
@@ -72,6 +73,7 @@ func (e *Entry) processPrefix(src any) (*netip.Prefix, IPType, error) {
}
case netip.Addr:
+ src = src.Unmap()
switch {
case src.Is4():
prefix := netip.PrefixFrom(src, 32)
@@ -84,6 +86,7 @@ func (e *Entry) processPrefix(src any) (*netip.Prefix, IPType, error) {
}
case *netip.Addr:
+ *src = (*src).Unmap()
switch {
case src.Is4():
prefix := netip.PrefixFrom(*src, 32)
@@ -99,9 +102,28 @@ func (e *Entry) processPrefix(src any) (*netip.Prefix, IPType, error) {
ip := src.Addr()
switch {
case ip.Is4():
- return &src, IPv4, nil
+ prefix, err := ip.Prefix(src.Bits())
+ if err != nil {
+ return nil, "", ErrInvalidPrefix
+ }
+ return &prefix, IPv4, nil
+ case ip.Is4In6():
+ ip = ip.Unmap()
+ bits := src.Bits()
+ if bits < 96 {
+ return nil, "", ErrInvalidPrefix
+ }
+ prefix, err := ip.Prefix(bits - 96)
+ if err != nil {
+ return nil, "", ErrInvalidPrefix
+ }
+ return &prefix, IPv4, nil
case ip.Is6():
- return &src, IPv6, nil
+ prefix, err := ip.Prefix(src.Bits())
+ if err != nil {
+ return nil, "", ErrInvalidPrefix
+ }
+ return &prefix, IPv6, nil
default:
return nil, "", ErrInvalidIPLength
}
@@ -110,9 +132,28 @@ func (e *Entry) processPrefix(src any) (*netip.Prefix, IPType, error) {
ip := src.Addr()
switch {
case ip.Is4():
- return src, IPv4, nil
+ prefix, err := ip.Prefix(src.Bits())
+ if err != nil {
+ return nil, "", ErrInvalidPrefix
+ }
+ return &prefix, IPv4, nil
+ case ip.Is4In6():
+ ip = ip.Unmap()
+ bits := src.Bits()
+ if bits < 96 {
+ return nil, "", ErrInvalidPrefix
+ }
+ prefix, err := ip.Prefix(bits - 96)
+ if err != nil {
+ return nil, "", ErrInvalidPrefix
+ }
+ return &prefix, IPv4, nil
case ip.Is6():
- return src, IPv6, nil
+ prefix, err := ip.Prefix(src.Bits())
+ if err != nil {
+ return nil, "", ErrInvalidPrefix
+ }
+ return &prefix, IPv6, nil
default:
return nil, "", ErrInvalidIPLength
}
@@ -126,42 +167,44 @@ func (e *Entry) processPrefix(src any) (*netip.Prefix, IPType, error) {
return nil, "", ErrCommentLine
}
- _, network, err := net.ParseCIDR(src)
- switch err {
- case nil:
- prefix, err2 := netip.ParsePrefix(network.String())
- if err2 != nil {
+ switch strings.Contains(src, "/") {
+ case true: // src is CIDR notation
+ ip, network, err := net.ParseCIDR(src)
+ if err != nil {
+ return nil, "", ErrInvalidCIDR
+ }
+ addr, ok := netipx.FromStdIP(ip)
+ if !ok {
+ return nil, "", ErrInvalidIP
+ }
+ if addr.Unmap().Is4() && strings.Contains(network.String(), "::") { // src is invalid IPv4-mapped IPv6 address
+ return nil, "", ErrInvalidCIDR
+ }
+ prefix, ok := netipx.FromStdIPNet(network)
+ if !ok {
return nil, "", ErrInvalidIPNet
}
- ip := prefix.Addr()
+
+ addr = prefix.Addr().Unmap()
switch {
- case ip.Is4():
+ case addr.Is4():
return &prefix, IPv4, nil
- case ip.Is6():
+ case addr.Is6():
return &prefix, IPv6, nil
default:
return nil, "", ErrInvalidIPLength
}
- default:
+ case false: // src is IP address
ip, err := netip.ParseAddr(src)
if err != nil {
- return nil, "", err
+ return nil, "", ErrInvalidIP
}
+ ip = ip.Unmap()
switch {
case ip.Is4():
prefix := netip.PrefixFrom(ip, 32)
return &prefix, IPv4, nil
- case ip.Is4In6():
- _, network, err2 := net.ParseCIDR(src + "/128")
- if err2 != nil {
- return nil, "", ErrInvalidIPNet
- }
- prefix, err3 := netip.ParsePrefix(network.String())
- if err3 != nil {
- return nil, "", ErrInvalidIPNet
- }
- return &prefix, IPv4, nil
case ip.Is6():
prefix := netip.PrefixFrom(ip, 128)
return &prefix, IPv6, nil
diff --git a/lib/error.go b/lib/error.go
index 1b8e4518..80dcc736 100644
--- a/lib/error.go
+++ b/lib/error.go
@@ -10,6 +10,8 @@ var (
ErrInvalidIP = errors.New("invalid IP address")
ErrInvalidIPLength = errors.New("invalid IP address length")
ErrInvalidIPNet = errors.New("invalid IPNet address")
+ ErrInvalidCIDR = errors.New("invalid CIDR")
+ ErrInvalidPrefix = errors.New("invalid prefix")
ErrInvalidPrefixType = errors.New("invalid prefix type")
ErrCommentLine = errors.New("comment line")
)