Parses a comma-delimited list of IP addresses, IP ranges, CIDR blocks, or hostnames and returns a slice of []IPRange. e.g. "144.142.126.222:144.142.126.244,144.142.126.254,192.168.0.0/16,host.docker.internal"
(str string)
| 294 | // |
| 295 | // e.g. "144.142.126.222:144.142.126.244,144.142.126.254,192.168.0.0/16,host.docker.internal" |
| 296 | func getIPsFromString(str string) ([]x.IPRange, error) { |
| 297 | if str == "" { |
| 298 | return []x.IPRange{}, nil |
| 299 | } |
| 300 | |
| 301 | var ipRanges []x.IPRange |
| 302 | rangeStrings := strings.Split(str, ",") |
| 303 | |
| 304 | for _, s := range rangeStrings { |
| 305 | isIPv6 := strings.Contains(s, "::") |
| 306 | tuple := strings.Split(s, ":") |
| 307 | switch { |
| 308 | case isIPv6 || len(tuple) == 1: |
| 309 | if !strings.Contains(s, "/") { |
| 310 | // string is hostname like host.docker.internal, |
| 311 | // or IPv4 address like 144.124.126.254, |
| 312 | // or IPv6 address like fd03:b188:0f3c:9ec4::babe:face |
| 313 | ipAddr := net.ParseIP(s) |
| 314 | if ipAddr != nil { |
| 315 | ipRanges = append(ipRanges, x.IPRange{Lower: ipAddr, Upper: ipAddr}) |
| 316 | } else { |
| 317 | ipAddrs, err := net.LookupIP(s) |
| 318 | if err != nil { |
| 319 | return nil, errors.Errorf("invalid IP address or hostname: %s", s) |
| 320 | } |
| 321 | |
| 322 | for _, addr := range ipAddrs { |
| 323 | ipRanges = append(ipRanges, x.IPRange{Lower: addr, Upper: addr}) |
| 324 | } |
| 325 | } |
| 326 | } else { |
| 327 | // string is CIDR block like 192.168.0.0/16 or fd03:b188:0f3c:9ec4::/64 |
| 328 | rangeLo, network, err := net.ParseCIDR(s) |
| 329 | if err != nil { |
| 330 | return nil, errors.Errorf("invalid CIDR block: %s", s) |
| 331 | } |
| 332 | |
| 333 | addrLen, maskLen := len(rangeLo), len(network.Mask) |
| 334 | rangeHi := make(net.IP, len(rangeLo)) |
| 335 | copy(rangeHi, rangeLo) |
| 336 | for i := 1; i <= maskLen; i++ { |
| 337 | rangeHi[addrLen-i] |= ^network.Mask[maskLen-i] |
| 338 | } |
| 339 | |
| 340 | ipRanges = append(ipRanges, x.IPRange{Lower: rangeLo, Upper: rangeHi}) |
| 341 | } |
| 342 | case len(tuple) == 2: |
| 343 | // string is range like a.b.c.d:w.x.y.z |
| 344 | rangeLo := net.ParseIP(tuple[0]) |
| 345 | rangeHi := net.ParseIP(tuple[1]) |
| 346 | switch { |
| 347 | case rangeLo == nil: |
| 348 | return nil, errors.Errorf("invalid IP address: %s", tuple[0]) |
| 349 | case rangeHi == nil: |
| 350 | return nil, errors.Errorf("invalid IP address: %s", tuple[1]) |
| 351 | case bytes.Compare(rangeLo, rangeHi) > 0: |
| 352 | return nil, errors.Errorf("inverted IP address range: %s", s) |
| 353 | } |