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