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