ipfamily.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. Copyright 2018 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package net
  14. import (
  15. "fmt"
  16. "net"
  17. )
  18. // IPFamily refers to a specific family if not empty, i.e. "4" or "6".
  19. type IPFamily string
  20. // Constants for valid IPFamilys:
  21. const (
  22. IPFamilyUnknown IPFamily = ""
  23. IPv4 IPFamily = "4"
  24. IPv6 IPFamily = "6"
  25. )
  26. // IsDualStackIPs returns true if:
  27. // - all elements of ips are valid
  28. // - at least one IP from each family (v4 and v6) is present
  29. func IsDualStackIPs(ips []net.IP) (bool, error) {
  30. v4Found := false
  31. v6Found := false
  32. for i, ip := range ips {
  33. switch IPFamilyOf(ip) {
  34. case IPv4:
  35. v4Found = true
  36. case IPv6:
  37. v6Found = true
  38. default:
  39. return false, fmt.Errorf("invalid IP[%d]: %v", i, ip)
  40. }
  41. }
  42. return (v4Found && v6Found), nil
  43. }
  44. // IsDualStackIPStrings returns true if:
  45. // - all elements of ips can be parsed as IPs
  46. // - at least one IP from each family (v4 and v6) is present
  47. func IsDualStackIPStrings(ips []string) (bool, error) {
  48. parsedIPs := make([]net.IP, 0, len(ips))
  49. for i, ip := range ips {
  50. parsedIP := ParseIPSloppy(ip)
  51. if parsedIP == nil {
  52. return false, fmt.Errorf("invalid IP[%d]: %v", i, ip)
  53. }
  54. parsedIPs = append(parsedIPs, parsedIP)
  55. }
  56. return IsDualStackIPs(parsedIPs)
  57. }
  58. // IsDualStackCIDRs returns true if:
  59. // - all elements of cidrs are non-nil
  60. // - at least one CIDR from each family (v4 and v6) is present
  61. func IsDualStackCIDRs(cidrs []*net.IPNet) (bool, error) {
  62. v4Found := false
  63. v6Found := false
  64. for i, cidr := range cidrs {
  65. switch IPFamilyOfCIDR(cidr) {
  66. case IPv4:
  67. v4Found = true
  68. case IPv6:
  69. v6Found = true
  70. default:
  71. return false, fmt.Errorf("invalid CIDR[%d]: %v", i, cidr)
  72. }
  73. }
  74. return (v4Found && v6Found), nil
  75. }
  76. // IsDualStackCIDRStrings returns if
  77. // - all elements of cidrs can be parsed as CIDRs
  78. // - at least one CIDR from each family (v4 and v6) is present
  79. func IsDualStackCIDRStrings(cidrs []string) (bool, error) {
  80. parsedCIDRs, err := ParseCIDRs(cidrs)
  81. if err != nil {
  82. return false, err
  83. }
  84. return IsDualStackCIDRs(parsedCIDRs)
  85. }
  86. // IPFamilyOf returns the IP family of ip, or IPFamilyUnknown if it is invalid.
  87. func IPFamilyOf(ip net.IP) IPFamily {
  88. switch {
  89. case ip.To4() != nil:
  90. return IPv4
  91. case ip.To16() != nil:
  92. return IPv6
  93. default:
  94. return IPFamilyUnknown
  95. }
  96. }
  97. // IPFamilyOfString returns the IP family of ip, or IPFamilyUnknown if ip cannot
  98. // be parsed as an IP.
  99. func IPFamilyOfString(ip string) IPFamily {
  100. return IPFamilyOf(ParseIPSloppy(ip))
  101. }
  102. // IPFamilyOfCIDR returns the IP family of cidr.
  103. func IPFamilyOfCIDR(cidr *net.IPNet) IPFamily {
  104. if cidr == nil {
  105. return IPFamilyUnknown
  106. }
  107. return IPFamilyOf(cidr.IP)
  108. }
  109. // IPFamilyOfCIDRString returns the IP family of cidr.
  110. func IPFamilyOfCIDRString(cidr string) IPFamily {
  111. ip, _, _ := ParseCIDRSloppy(cidr)
  112. return IPFamilyOf(ip)
  113. }
  114. // IsIPv6 returns true if netIP is IPv6 (and false if it is IPv4, nil, or invalid).
  115. func IsIPv6(netIP net.IP) bool {
  116. return IPFamilyOf(netIP) == IPv6
  117. }
  118. // IsIPv6String returns true if ip contains a single IPv6 address and nothing else. It
  119. // returns false if ip is an empty string, an IPv4 address, or anything else that is not a
  120. // single IPv6 address.
  121. func IsIPv6String(ip string) bool {
  122. return IPFamilyOfString(ip) == IPv6
  123. }
  124. // IsIPv6CIDR returns true if a cidr is a valid IPv6 CIDR. It returns false if cidr is
  125. // nil or an IPv4 CIDR. Its behavior is not defined if cidr is invalid.
  126. func IsIPv6CIDR(cidr *net.IPNet) bool {
  127. return IPFamilyOfCIDR(cidr) == IPv6
  128. }
  129. // IsIPv6CIDRString returns true if cidr contains a single IPv6 CIDR and nothing else. It
  130. // returns false if cidr is an empty string, an IPv4 CIDR, or anything else that is not a
  131. // single valid IPv6 CIDR.
  132. func IsIPv6CIDRString(cidr string) bool {
  133. return IPFamilyOfCIDRString(cidr) == IPv6
  134. }
  135. // IsIPv4 returns true if netIP is IPv4 (and false if it is IPv6, nil, or invalid).
  136. func IsIPv4(netIP net.IP) bool {
  137. return IPFamilyOf(netIP) == IPv4
  138. }
  139. // IsIPv4String returns true if ip contains a single IPv4 address and nothing else. It
  140. // returns false if ip is an empty string, an IPv6 address, or anything else that is not a
  141. // single IPv4 address.
  142. func IsIPv4String(ip string) bool {
  143. return IPFamilyOfString(ip) == IPv4
  144. }
  145. // IsIPv4CIDR returns true if cidr is a valid IPv4 CIDR. It returns false if cidr is nil
  146. // or an IPv6 CIDR. Its behavior is not defined if cidr is invalid.
  147. func IsIPv4CIDR(cidr *net.IPNet) bool {
  148. return IPFamilyOfCIDR(cidr) == IPv4
  149. }
  150. // IsIPv4CIDRString returns true if cidr contains a single IPv4 CIDR and nothing else. It
  151. // returns false if cidr is an empty string, an IPv6 CIDR, or anything else that is not a
  152. // single valid IPv4 CIDR.
  153. func IsIPv4CIDRString(cidr string) bool {
  154. return IPFamilyOfCIDRString(cidr) == IPv4
  155. }