parseIPRange parses an IP range in the format "start-end" and converts it to a iprange.Range. If allowedNets are supplied, then each IP in the range is checked that it belongs to at least one of them. IPs in the range can be zero prefixed, e.g. "::1" or "0.0.0.1", however they should not overlap wit
(ipRange string, allowedNets ...*net.IPNet)
| 1007 | // returned combined with the first allowed network they are within. |
| 1008 | // If no allowedNets supplied they are returned as-is. |
| 1009 | func parseIPRange(ipRange string, allowedNets ...*net.IPNet) (*iprange.Range, error) { |
| 1010 | inAllowedNet := func(ipAddress net.IP, allowedNet *net.IPNet) net.IP { |
| 1011 | if ipAddress == nil { |
| 1012 | return nil |
| 1013 | } |
| 1014 | |
| 1015 | ipv4 := ipAddress.To4() |
| 1016 | |
| 1017 | // Only match IPv6 addresses against IPv6 networks. |
| 1018 | if ipv4 == nil && allowedNet.IP.To4() != nil { |
| 1019 | return nil |
| 1020 | } |
| 1021 | |
| 1022 | // Combine IP with network prefix if IP starts with a zero. |
| 1023 | // If IP is v4, then compare against 4-byte representation, otherwise use 16 byte representation. |
| 1024 | if (ipv4 != nil && ipv4[0] == 0) || (ipv4 == nil && ipAddress[0] == 0) { |
| 1025 | allowedNet16 := allowedNet.IP.To16() |
| 1026 | ipCombined := make(net.IP, net.IPv6len) |
| 1027 | for i, b := range ipAddress { |
| 1028 | ipCombined[i] = allowedNet16[i] | b |
| 1029 | } |
| 1030 | |
| 1031 | ipAddress = ipCombined |
| 1032 | } |
| 1033 | |
| 1034 | // Check start IP is within one of the allowed networks. |
| 1035 | if !allowedNet.Contains(ipAddress) { |
| 1036 | return nil |
| 1037 | } |
| 1038 | |
| 1039 | return ipAddress |
| 1040 | } |
| 1041 | |
| 1042 | rangeParts := strings.SplitN(ipRange, "-", 2) |
| 1043 | if len(rangeParts) != 2 { |
| 1044 | return nil, fmt.Errorf("IP range %q must contain start and end IP addresses", ipRange) |
| 1045 | } |
| 1046 | |
| 1047 | startIP := net.ParseIP(rangeParts[0]) |
| 1048 | endIP := net.ParseIP(rangeParts[1]) |
| 1049 | |
| 1050 | if startIP == nil { |
| 1051 | return nil, fmt.Errorf("Start IP %q is invalid", rangeParts[0]) |
| 1052 | } |
| 1053 | |
| 1054 | if endIP == nil { |
| 1055 | return nil, fmt.Errorf("End IP %q is invalid", rangeParts[1]) |
| 1056 | } |
| 1057 | |
| 1058 | if bytes.Compare(startIP, endIP) > 0 { |
| 1059 | return nil, fmt.Errorf("Start IP %q must be less than End IP %q", startIP, endIP) |
| 1060 | } |
| 1061 | |
| 1062 | if len(allowedNets) > 0 { |
| 1063 | matchFound := false |
| 1064 | for _, allowedNet := range allowedNets { |
| 1065 | if allowedNet == nil { |
| 1066 | return nil, errors.New("Invalid allowed network") |
searching dependent graphs…