diff options
| author | Loyalsoldier <[email protected]> | 2024-07-06 15:04:36 +0800 |
|---|---|---|
| committer | Loyalsoldier <[email protected]> | 2024-07-06 15:04:36 +0800 |
| commit | 5843ee29c435b393bec57a367775c2f4e266eedc (patch) | |
| tree | 7bbfde5a646c6f31f57418666b362038e8771c15 | |
| parent | 2c15c6946d02d63f9f94d23bc33b29941786564a (diff) | |
Fix: processing IPv4-mapped IPv6 address
| -rw-r--r-- | lib/entry.go | 93 | ||||
| -rw-r--r-- | lib/error.go | 2 |
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") ) |
