open-vault/helper/parseip/parseip.go

77 lines
2 KiB
Go
Raw Normal View History

// 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, "/")
}