...

Source file src/k8s.io/utils/net/ipfamily.go

Documentation: k8s.io/utils/net

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

View as plain text