77 lines
2.0 KiB
Go
77 lines
2.0 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package parseip
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"k8s.io/utils/net"
|
|
)
|
|
|
|
// In Go 1.17 the behaviour of net.ParseIP and net.ParseCIDR changed
|
|
// (https://golang.org/doc/go1.17#net) so that leading zeros in the input results
|
|
// in an error. This package contains helpers that strip leading zeroes so as
|
|
// to avoid those errors.
|
|
|
|
// You should probably not be using anything here unless you've found a new place
|
|
// where IPs/CIDRs are read from storage and re-parsed.
|
|
|
|
// trimLeadingZeroes returns its input trimmed of any leading zeroes.
|
|
func trimLeadingZeroes(s string) string {
|
|
for i, r := range s {
|
|
if r == '0' {
|
|
continue
|
|
}
|
|
return s[i:]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// trimLeadingZeroesIPv4 takes an IPv4 string and returns the input
|
|
// trimmed of any excess leading zeroes in each octet.
|
|
func trimLeadingZeroesIPv4(s string) string {
|
|
if len(s) == 0 {
|
|
return s
|
|
}
|
|
|
|
pieces := strings.Split(s, ".")
|
|
var sb strings.Builder
|
|
for i, piece := range pieces {
|
|
trimmed := trimLeadingZeroes(piece)
|
|
if trimmed == "" && len(piece) > 0 {
|
|
sb.WriteByte('0')
|
|
} else {
|
|
sb.WriteString(trimmed)
|
|
}
|
|
if i != len(pieces)-1 {
|
|
sb.WriteByte('.')
|
|
}
|
|
}
|
|
return sb.String()
|
|
}
|
|
|
|
// trimLeadingZeroesIP does the same work as trimLeadingZeroesIPv4 but also accepts
|
|
// an IPv6 address that may contain an IPv4 address representation. Only decimal
|
|
// IPv4 addresses get zero-stripped.
|
|
func trimLeadingZeroesIP(s string) string {
|
|
for i := len(s) - 1; i >= 0; i-- {
|
|
if s[i] == ':' && net.ParseIPSloppy(s[i+1:]) != nil {
|
|
return s[:i+1] + trimLeadingZeroesIPv4(s[i+1:])
|
|
}
|
|
}
|
|
return trimLeadingZeroesIPv4(s)
|
|
}
|
|
|
|
// TrimLeadingZeroesCIDR does the same thing as trimLeadingZeroesIP but expects
|
|
// a CIDR address as input. If the input isn't a valid CIDR address, it is returned
|
|
// unchanged.
|
|
func TrimLeadingZeroesCIDR(s string) string {
|
|
pieces := strings.Split(s, "/")
|
|
if len(pieces) != 2 {
|
|
return s
|
|
}
|
|
pieces[0] = trimLeadingZeroesIP(pieces[0])
|
|
return strings.Join(pieces, "/")
|
|
}
|