@@ -19,6 +19,7 @@ package net
1919import (
2020 "fmt"
2121 "net"
22+ "net/netip"
2223
2324 forkednet "k8s.io/utils/internal/third_party/forked/golang/net"
2425)
@@ -28,6 +29,8 @@ import (
2829// non-validated input strings. It should be used instead of net.ParseIP (which rejects
2930// some strings we need to accept for backward compatibility) and the old
3031// netutilsv1.ParseIPSloppy.
32+ //
33+ // Compare ParseAddr, which returns a netip.Addr but is otherwise identical.
3134func ParseIP (ipStr string ) (net.IP , error ) {
3235 // Note: if we want to get rid of forkednet, we should be able to use some
3336 // invocation of regexp.ReplaceAllString to get rid of leading 0s in ipStr.
@@ -47,6 +50,25 @@ func ParseIP(ipStr string) (net.IP, error) {
4750 return nil , fmt .Errorf ("not a valid IP address" )
4851}
4952
53+ // ParseAddr parses an IPv4 or IPv6 address to a netip.Addr. This accepts both fully-valid
54+ // IP addresses and irregular/ambiguous forms, making it usable for both validated and
55+ // non-validated input strings. As compared to netip.ParseAddr:
56+ //
57+ // - It accepts IPv4 IPs with extra leading "0"s, for backward compatibility.
58+ // - It rejects IPs with attached zone identifiers (e.g. `"fe80::1234%eth0"`).
59+ // - It converts "IPv4-mapped IPv6" addresses (e.g. `"::ffff:1.2.3.4"`) to the
60+ // corresponding "plain" IPv4 values (e.g. `"1.2.3.4"`). That is, it never returns an
61+ // address for which `Is4In6()` would return `true`.
62+ //
63+ // Compare ParseIP, which returns a net.IP but is otherwise identical.
64+ func ParseAddr (ipStr string ) (netip.Addr , error ) {
65+ // To ensure identical parsing, we use ParseIP and then convert. (If ParseIP
66+ // returns a nil ip, AddrFromIP will convert that to the zero/invalid netip.Addr,
67+ // which is what we want.)
68+ ip , err := ParseIP (ipStr )
69+ return AddrFromIP (ip ), err
70+ }
71+
5072// ParseIPNet parses an IPv4 or IPv6 CIDR string representing a subnet or mask, to a
5173// *net.IPNet. This accepts both fully-valid CIDR values and irregular/ambiguous forms,
5274// making it usable for both validated and non-validated input strings. It should be used
@@ -56,6 +78,8 @@ func ParseIP(ipStr string) (net.IP, error) {
5678// The return value is equivalent to the second return value from net.ParseCIDR. Note that
5779// this means that if the CIDR string has bits set beyond the prefix length (e.g., the "5"
5880// in "192.168.1.5/24"), those bits are simply discarded.
81+ //
82+ // Compare ParsePrefix, which returns a netip.Prefix but is otherwise identical.
5983func ParseIPNet (cidrStr string ) (* net.IPNet , error ) {
6084 // Note: if we want to get rid of forkednet, we should be able to use some
6185 // invocation of regexp.ReplaceAllString to get rid of leading 0s in cidrStr.
@@ -73,3 +97,25 @@ func ParseIPNet(cidrStr string) (*net.IPNet, error) {
7397 }
7498 return nil , fmt .Errorf ("not a valid CIDR value" )
7599}
100+
101+ // ParsePrefix parses an IPv4 or IPv6 CIDR string representing a subnet or mask, to a
102+ // netip.Prefix. This accepts both fully-valid CIDR values and irregular/ambiguous forms,
103+ // making it usable for both validated and non-validated input strings. As compared to
104+ // netip.ParsePrefix:
105+ //
106+ // - It accepts IPv4 IPs with extra leading "0"s, for backward compatibility.
107+ // - It converts "IPv4-mapped IPv6" addresses (e.g. `"::ffff:1.2.3.0/120"`) to the
108+ // corresponding "plain" IPv4 values (e.g. `"1.2.3.0/24"`). That is, it never returns
109+ // a prefix for which `.Addr().Is4In6()` would return `true`.
110+ // - When given a CIDR string with bits set beyond the prefix length, like
111+ // `"192.168.1.5/24"`, it discards those extra bits (the equivalent of calling
112+ // .Masked() on the return value of netip.ParsePrefix).
113+ //
114+ // Compare ParseIPNet, which returns a *net.IPNet but is otherwise identical.
115+ func ParsePrefix (cidrStr string ) (netip.Prefix , error ) {
116+ // To ensure identical parsing, we use ParseIPNet and then convert. (If ParseIPNet
117+ // returns nil, PrefixFromIPNet will convert that to the zero/invalid
118+ // netip.Prefix, which is what we want.)
119+ ipnet , err := ParseIPNet (cidrStr )
120+ return PrefixFromIPNet (ipnet ), err
121+ }
0 commit comments