...

Source file src/k8s.io/utils/internal/third_party/forked/golang/net/ip.go

Documentation: k8s.io/utils/internal/third_party/forked/golang/net

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // IP address manipulations
     6  //
     7  // IPv4 addresses are 4 bytes; IPv6 addresses are 16 bytes.
     8  // An IPv4 address can be converted to an IPv6 address by
     9  // adding a canonical prefix (10 zeros, 2 0xFFs).
    10  // This library accepts either size of byte slice but always
    11  // returns 16-byte addresses.
    12  
    13  package net
    14  
    15  ///////////////////////////////////////////////////////////////////////////////
    16  // NOTE: This file was forked because we need to maintain backwards-compatible
    17  // IP parsing logic, which was changed in a correct but incompatible way in
    18  // go-1.17.
    19  //
    20  // See https://issue.k8s.io/100895
    21  ///////////////////////////////////////////////////////////////////////////////
    22  
    23  import (
    24  	stdnet "net"
    25  )
    26  
    27  //
    28  // Lean on the standard net lib as much as possible.
    29  //
    30  
    31  type IP = stdnet.IP
    32  type IPNet = stdnet.IPNet
    33  type ParseError = stdnet.ParseError
    34  
    35  const IPv4len = stdnet.IPv4len
    36  const IPv6len = stdnet.IPv6len
    37  
    38  var CIDRMask = stdnet.CIDRMask
    39  var IPv4 = stdnet.IPv4
    40  
    41  // Parse IPv4 address (d.d.d.d).
    42  func parseIPv4(s string) IP {
    43  	var p [IPv4len]byte
    44  	for i := 0; i < IPv4len; i++ {
    45  		if len(s) == 0 {
    46  			// Missing octets.
    47  			return nil
    48  		}
    49  		if i > 0 {
    50  			if s[0] != '.' {
    51  				return nil
    52  			}
    53  			s = s[1:]
    54  		}
    55  		n, c, ok := dtoi(s)
    56  		if !ok || n > 0xFF {
    57  			return nil
    58  		}
    59  		//
    60  		// NOTE: This correct check was added for go-1.17, but is a
    61  		// backwards-incompatible change for kubernetes users, who might have
    62  		// stored data which uses these leading zeroes already.
    63  		//
    64  		// See https://issue.k8s.io/100895
    65  		//
    66  		//if c > 1 && s[0] == '0' {
    67  		//	// Reject non-zero components with leading zeroes.
    68  		//	return nil
    69  		//}
    70  		s = s[c:]
    71  		p[i] = byte(n)
    72  	}
    73  	if len(s) != 0 {
    74  		return nil
    75  	}
    76  	return IPv4(p[0], p[1], p[2], p[3])
    77  }
    78  
    79  // parseIPv6 parses s as a literal IPv6 address described in RFC 4291
    80  // and RFC 5952.
    81  func parseIPv6(s string) (ip IP) {
    82  	ip = make(IP, IPv6len)
    83  	ellipsis := -1 // position of ellipsis in ip
    84  
    85  	// Might have leading ellipsis
    86  	if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
    87  		ellipsis = 0
    88  		s = s[2:]
    89  		// Might be only ellipsis
    90  		if len(s) == 0 {
    91  			return ip
    92  		}
    93  	}
    94  
    95  	// Loop, parsing hex numbers followed by colon.
    96  	i := 0
    97  	for i < IPv6len {
    98  		// Hex number.
    99  		n, c, ok := xtoi(s)
   100  		if !ok || n > 0xFFFF {
   101  			return nil
   102  		}
   103  
   104  		// If followed by dot, might be in trailing IPv4.
   105  		if c < len(s) && s[c] == '.' {
   106  			if ellipsis < 0 && i != IPv6len-IPv4len {
   107  				// Not the right place.
   108  				return nil
   109  			}
   110  			if i+IPv4len > IPv6len {
   111  				// Not enough room.
   112  				return nil
   113  			}
   114  			ip4 := parseIPv4(s)
   115  			if ip4 == nil {
   116  				return nil
   117  			}
   118  			ip[i] = ip4[12]
   119  			ip[i+1] = ip4[13]
   120  			ip[i+2] = ip4[14]
   121  			ip[i+3] = ip4[15]
   122  			s = ""
   123  			i += IPv4len
   124  			break
   125  		}
   126  
   127  		// Save this 16-bit chunk.
   128  		ip[i] = byte(n >> 8)
   129  		ip[i+1] = byte(n)
   130  		i += 2
   131  
   132  		// Stop at end of string.
   133  		s = s[c:]
   134  		if len(s) == 0 {
   135  			break
   136  		}
   137  
   138  		// Otherwise must be followed by colon and more.
   139  		if s[0] != ':' || len(s) == 1 {
   140  			return nil
   141  		}
   142  		s = s[1:]
   143  
   144  		// Look for ellipsis.
   145  		if s[0] == ':' {
   146  			if ellipsis >= 0 { // already have one
   147  				return nil
   148  			}
   149  			ellipsis = i
   150  			s = s[1:]
   151  			if len(s) == 0 { // can be at end
   152  				break
   153  			}
   154  		}
   155  	}
   156  
   157  	// Must have used entire string.
   158  	if len(s) != 0 {
   159  		return nil
   160  	}
   161  
   162  	// If didn't parse enough, expand ellipsis.
   163  	if i < IPv6len {
   164  		if ellipsis < 0 {
   165  			return nil
   166  		}
   167  		n := IPv6len - i
   168  		for j := i - 1; j >= ellipsis; j-- {
   169  			ip[j+n] = ip[j]
   170  		}
   171  		for j := ellipsis + n - 1; j >= ellipsis; j-- {
   172  			ip[j] = 0
   173  		}
   174  	} else if ellipsis >= 0 {
   175  		// Ellipsis must represent at least one 0 group.
   176  		return nil
   177  	}
   178  	return ip
   179  }
   180  
   181  // ParseIP parses s as an IP address, returning the result.
   182  // The string s can be in IPv4 dotted decimal ("192.0.2.1"), IPv6
   183  // ("2001:db8::68"), or IPv4-mapped IPv6 ("::ffff:192.0.2.1") form.
   184  // If s is not a valid textual representation of an IP address,
   185  // ParseIP returns nil.
   186  func ParseIP(s string) IP {
   187  	for i := 0; i < len(s); i++ {
   188  		switch s[i] {
   189  		case '.':
   190  			return parseIPv4(s)
   191  		case ':':
   192  			return parseIPv6(s)
   193  		}
   194  	}
   195  	return nil
   196  }
   197  
   198  // ParseCIDR parses s as a CIDR notation IP address and prefix length,
   199  // like "192.0.2.0/24" or "2001:db8::/32", as defined in
   200  // RFC 4632 and RFC 4291.
   201  //
   202  // It returns the IP address and the network implied by the IP and
   203  // prefix length.
   204  // For example, ParseCIDR("192.0.2.1/24") returns the IP address
   205  // 192.0.2.1 and the network 192.0.2.0/24.
   206  func ParseCIDR(s string) (IP, *IPNet, error) {
   207  	i := indexByteString(s, '/')
   208  	if i < 0 {
   209  		return nil, nil, &ParseError{Type: "CIDR address", Text: s}
   210  	}
   211  	addr, mask := s[:i], s[i+1:]
   212  	iplen := IPv4len
   213  	ip := parseIPv4(addr)
   214  	if ip == nil {
   215  		iplen = IPv6len
   216  		ip = parseIPv6(addr)
   217  	}
   218  	n, i, ok := dtoi(mask)
   219  	if ip == nil || !ok || i != len(mask) || n < 0 || n > 8*iplen {
   220  		return nil, nil, &ParseError{Type: "CIDR address", Text: s}
   221  	}
   222  	m := CIDRMask(n, 8*iplen)
   223  	return ip, &IPNet{IP: ip.Mask(m), Mask: m}, nil
   224  }
   225  
   226  // This is copied from go/src/internal/bytealg, which includes versions
   227  // optimized for various platforms.  Those optimizations are elided here so we
   228  // don't have to maintain them.
   229  func indexByteString(s string, c byte) int {
   230  	for i := 0; i < len(s); i++ {
   231  		if s[i] == c {
   232  			return i
   233  		}
   234  	}
   235  	return -1
   236  }
   237  

View as plain text