// IPNetEqual checks if the two input IPNets are representing the same subnet. // For example, // 10.0.0.1/24 and 10.0.0.0/24 are the same subnet. // 10.0.0.1/24 and 10.0.0.0/25 are not the same subnet. func IPNetEqual(ipnet1, ipnet2 *net.IPNet) bool { if ipnet1 == nil || ipnet2 == nil { return false } if reflect.DeepEqual(ipnet1.Mask, ipnet2.Mask) && ipnet1.Contains(ipnet2.IP) && ipnet2.Contains(ipnet1.IP) { return true } return false }
func TestAllocate(t *testing.T) { subnet := net.IPNet{ IP: net.IPv4(0xab, 0xcd, 0xe0, 0x00), Mask: net.CIDRMask(20, 32), } conflicts := map[string]struct{}{} ipSet := map[string]struct{}{} // Only 4k IPs, in 0xfffff000. Guaranteed a collision for i := 0; i < 5000; i++ { ip, err := allocateIP(ipSet, subnet) if err != nil { continue } if _, ok := conflicts[ip]; ok { t.Fatalf("IP Double allocation: 0x%x", ip) } require.True(t, subnet.Contains(net.ParseIP(ip)), fmt.Sprintf("\"%s\" is not in %s", ip, subnet)) conflicts[ip] = struct{}{} } assert.Equal(t, len(conflicts), len(ipSet)) if len(conflicts) < 2500 || len(conflicts) > 4096 { // If the code's working, this is possible but *extremely* unlikely. // Probably a bug. t.Errorf("Too few conflicts: %d", len(conflicts)) } }
func getSuitableAddrs(addrs []*address, v4, v6, linklocal, loopback bool, re *regexp.Regexp, mask *net.IPNet) ([]*address, error) { ret := []*address{} for _, a := range addrs { if a.IsLoopback() && !loopback { continue } if !v6 && a.IsV6() { continue } if !v4 && a.IsV4() { continue } if !linklocal && a.IsLinkLocalUnicast() { continue } if !loopback && a.IsLoopback() { continue } if re != nil { if !re.MatchString(a.String()) { continue } } if mask != nil { if !mask.Contains(a.IP) { continue } } ret = append(ret, a) } if len(ret) == 0 { return nil, errors.New("unable to find suitable address") } return ret, nil }
// NextSubnetIP returns the next available IP address in a given subnet. func NextSubnetIP(subnet *net.IPNet, ipsInUse []net.IP) (net.IP, error) { ones, bits := subnet.Mask.Size() subnetMaskUint32 := ipUint32(net.IP(subnet.Mask)) inUse := big.NewInt(0) for _, ip := range ipsInUse { if !subnet.Contains(ip) { continue } index := ipIndex(ip, subnetMaskUint32) inUse = inUse.SetBit(inUse, index, 1) } // Now iterate through all addresses in the subnet and return the // first address that is not in use. We start at the first non- // reserved address, and stop short of the last address in the // subnet (i.e. all non-mask bits set), which is the broadcast // address for the subnet. n := ipUint32(subnet.IP) for i := reservedAddressRangeEnd + 1; i < (1<<uint64(bits-ones) - 1); i++ { ip := uint32IP(n + uint32(i)) if !ip.IsGlobalUnicast() { continue } index := ipIndex(ip, subnetMaskUint32) if inUse.Bit(index) == 0 { return ip, nil } } return nil, errors.Errorf("no addresses available in %s", subnet) }
// hasIP6Connected parses the list of remote addresses in /proc/net/{tcp,udp}6 or in // /proc/<pid>/net/{tcp,udp}6 and returns addresses that are contained within // the ipnet submitted. It always uses CIDR inclusion, even when only // searching for a single IP (but assuming a /128 bitmask). // Remote addresses exposed in /proc are in hexadecimal notation, and converted into byte slices // to use in ipnet.Contains() func hasIP6Connected(ip net.IP, ipnet *net.IPNet) (found bool, elements []element, err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("hasIP6Connected(): %v", e) } }() lns, err := procIP6Entries() if err != nil { panic(err) } // if the ipnet is nil, assume that its a full 128bits mask if ipnet == nil { ipnet = new(net.IPNet) ipnet.IP = ip ipnet.Mask = net.CIDRMask(net.IPv6len*8, net.IPv6len*8) } for _, ipent := range lns { fields := strings.Fields(ipent.line) if len(fields) < 4 { panic("/proc doesn't respect the expected format") } remote := strings.Split(fields[2], ":") if len(remote) != 2 { panic("remote isn't in the form <ip>:<port>") } remoteIP := hexToIP6(remote[0]) if remoteIP == nil { panic("failed to convert remote IP") } // if we've got a match, store the element if ipnet.Contains(remoteIP) { var el element el.RemoteAddr = remoteIP.String() remotePort, err := strconv.ParseUint(remote[1], 16, 16) if err != nil { panic("failed to convert remote port") } el.RemotePort = float64(remotePort) local := strings.Split(fields[1], ":") if len(local) != 2 { panic("local isn't in the form <ip>:<port>") } localAddr := hexToIP6(local[0]) if localAddr == nil { panic("failed to convert local ip") } el.LocalAddr = localAddr.String() localPort, err := strconv.ParseUint(local[1], 16, 16) if err != nil { panic("failed to convert local port") } el.LocalPort = float64(localPort) el.Namespace = ipent.nsIdentifier elements = append(elements, el) found = true } stats.Examined++ } return }
// GetIndexedIP returns a net.IP that is subnet.IP + index in the contiguous IP space. func GetIndexedIP(subnet *net.IPNet, index int) (net.IP, error) { ip := addIPOffset(bigForIP(subnet.IP), index) if !subnet.Contains(ip) { return nil, fmt.Errorf("can't generate IP with index %d from subnet. subnet too small. subnet: %q", index, subnet) } return ip, nil }
func (s *cidrSet) getBeginingAndEndIndices(cidr *net.IPNet) (begin, end int, err error) { begin, end = 0, s.maxCIDRs cidrMask := cidr.Mask maskSize, _ := cidrMask.Size() if !s.clusterCIDR.Contains(cidr.IP.Mask(s.clusterCIDR.Mask)) && !cidr.Contains(s.clusterCIDR.IP.Mask(cidr.Mask)) { return -1, -1, fmt.Errorf("cidr %v is out the range of cluster cidr %v", cidr, s.clusterCIDR) } if s.clusterMaskSize < maskSize { subNetMask := net.CIDRMask(s.subNetMaskSize, 32) begin, err = s.getIndexForCIDR(&net.IPNet{ IP: cidr.IP.To4().Mask(subNetMask), Mask: subNetMask, }) if err != nil { return -1, -1, err } ip := make([]byte, 4) ipInt := binary.BigEndian.Uint32(cidr.IP) | (^binary.BigEndian.Uint32(cidr.Mask)) binary.BigEndian.PutUint32(ip, ipInt) end, err = s.getIndexForCIDR(&net.IPNet{ IP: net.IP(ip).To4().Mask(subNetMask), Mask: subNetMask, }) if err != nil { return -1, -1, err } } return begin, end, nil }
func networkAddressForSubnet(subnet *net.IPNet) (net.IP, string, error) { ifaces, err := net.Interfaces() if err != nil { return net.IP{}, "", err } for _, iface := range ifaces { addrs, err := iface.Addrs() if err != nil { continue } for _, addr := range addrs { ip, _, err := net.ParseCIDR(addr.String()) if err != nil { continue } if subnet.Contains(ip) { return ip, iface.Name, nil } } } return net.IP{}, "", fmt.Errorf("No address found in subnet") }
// NetList : subnet helper function func NetList(ip net.IP, subnet net.IP) (IPlist []net.IP) { //ip, ipnet, err := net.ParseCIDR(cidrNet) mask := net.IPv4Mask(subnet[0], subnet[1], subnet[2], subnet[3]) ipnet := net.IPNet{ip, mask} for ip := ip.Mask(mask); ipnet.Contains(ip); incIP(ip) { IPlist = append(IPlist, net.IP{ip[0], ip[1], ip[2], ip[3]}) } return }
// Detects overlap between one IPNet and another func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool { if firstIP, _ := NetworkRange(netX); netY.Contains(firstIP) { return true } if firstIP, _ := NetworkRange(netY); netX.Contains(firstIP) { return true } return false }
// Checks whether the passed subnet is a superset or subset of any of the subset in this config db func (aSpace *addrSpace) contains(space string, nw *net.IPNet) bool { for k, v := range aSpace.subnets { if space == k.AddressSpace && k.ChildSubnet == "" { if nw.Contains(v.Pool.IP) || v.Pool.Contains(nw.IP) { return true } } } return false }
// SpanningCIDR computes network covers given IP addresses func SpanningCIDR(first, last net.IP) *net.IPNet { _, bits := last.DefaultMask().Size() var network net.IPNet for ones := bits; !network.Contains(first); ones-- { network.Mask = net.CIDRMask(ones, bits) network.IP = last.Mask(network.Mask) } return &network }
// Detects overlap between one IPNet and another func networkOverlaps(netX *net.IPNet, netY *net.IPNet) bool { firstIP, _ := networkRange(netX) if netY.Contains(firstIP) { return true } firstIP, _ = networkRange(netY) if netX.Contains(firstIP) { return true } return false }
func (d *Device) InNetwork(network net.IPNet) bool { if network.Contains(d.IP) { return true } for _, a := range d.Reverse { if !network.Contains(a) { continue } return true } return false }
// Marks all CIDRs with subNetMaskSize that belongs to serviceCIDR as used, // so that they won't be assignable. func (r *rangeAllocator) filterOutServiceRange(serviceCIDR *net.IPNet) { // Checks if service CIDR has a nonempty intersection with cluster CIDR. It is the case if either // clusterCIDR contains serviceCIDR with clusterCIDR's Mask applied (this means that clusterCIDR contains serviceCIDR) // or vice versa (which means that serviceCIDR contains clusterCIDR). if !r.clusterCIDR.Contains(serviceCIDR.IP.Mask(r.clusterCIDR.Mask)) && !serviceCIDR.Contains(r.clusterCIDR.IP.Mask(serviceCIDR.Mask)) { return } if err := r.cidrs.occupy(serviceCIDR); err != nil { glog.Errorf("Error filtering out service cidr %v: %v", serviceCIDR, err) } }
// NetworkOverlaps detects overlap between one IPNet and another func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool { // Check if both netX and netY are ipv4 or ipv6 if (netX.IP.To4() != nil && netY.IP.To4() != nil) || (netX.IP.To4() == nil && netY.IP.To4() == nil) { if firstIP, _ := NetworkRange(netX); netY.Contains(firstIP) { return true } if firstIP, _ := NetworkRange(netY); netX.Contains(firstIP) { return true } } return false }
func selectIPv4Address(addresses []netlink.Addr, selector *net.IPNet) (netlink.Addr, error) { if len(addresses) == 0 { return netlink.Addr{}, fmt.Errorf("unable to select an address as the address pool is empty") } if selector != nil { for _, addr := range addresses { if selector.Contains(addr.IP) { return addr, nil } } } return addresses[0], nil }
func filterOnSubnet(subnet net.IPNet, dkcs []docker.Container) (good []docker.Container, bad []interface{}) { for _, dkc := range dkcs { dkIP := net.ParseIP(dkc.IP) if subnet.Contains(dkIP) { good = append(good, dkc) } else { bad = append(bad, dkc) } } return good, bad }
func (dynamicIPSelector) SelectIP(subnet *net.IPNet, existing []net.IP) (net.IP, error) { exists := make(map[string]bool) for _, e := range existing { exists[e.String()] = true } for i := subnet.IP; subnet.Contains(i); i = next(i) { if !exists[i.String()] { return i, nil } } return nil, ErrInsufficientIPs }
func generateAllInSubnet(ipNet *net.IPNet, subnet *scanner.Subnet) { inc := func(ip net.IP) { for j := len(ip) - 1; j >= 0; j-- { ip[j]++ if ip[j] > 0 { break } } } for ip := ipNet.IP.Mask(ipNet.Mask); ipNet.Contains(ip); inc(ip) { subnet.Nodes[ip.String()] = &scanner.NodeStatus{scanner.UNKNOWN} subnet.OrderedAddresses = append(subnet.OrderedAddresses, ip.String()) } }
func checkRouteConflict(nlh *netlink.Handle, address *net.IPNet, family int) error { routes, err := nlh.RouteList(nil, family) if err != nil { return err } for _, route := range routes { if route.Dst != nil { if route.Dst.Contains(address.IP) || address.Contains(route.Dst.IP) { return fmt.Errorf("cannot program address %v in sandbox interface because it conflicts with existing route %s", address, route) } } } return nil }
// Ensures @ip is within @ipnet, and (if given) inclusive of @start and @end func validateRangeIP(ip net.IP, ipnet *net.IPNet, start net.IP, end net.IP) error { var err error // Make sure we can compare IPv4 addresses directly ip, err = canonicalizeIP(ip) if err != nil { return err } if !ipnet.Contains(ip) { return fmt.Errorf("%s not in network: %s", ip, ipnet) } if start != nil { start, err = canonicalizeIP(start) if err != nil { return err } if len(ip) != len(start) { return fmt.Errorf("%s %d not same size IP address as start %s %d", ip, len(ip), start, len(start)) } for i := 0; i < len(ip); i++ { if ip[i] > start[i] { break } else if ip[i] < start[i] { return fmt.Errorf("%s outside of network %s with start %s", ip, ipnet, start) } } } if end != nil { end, err = canonicalizeIP(end) if err != nil { return err } if len(ip) != len(end) { return fmt.Errorf("%s %d not same size IP address as end %s %d", ip, len(ip), end, len(end)) } for i := 0; i < len(ip); i++ { if ip[i] < end[i] { break } else if ip[i] > end[i] { return fmt.Errorf("%s outside of network %s with end %s", ip, ipnet, end) } } } return nil }
func findBridgeIP(bridgeName string, subnet net.IPNet) (net.IP, error) { netdev, err := common.GetBridgeNetDev(bridgeName) if err != nil { return nil, fmt.Errorf("Failed to get netdev for %q bridge: %s", bridgeName, err) } if len(netdev.CIDRs) == 0 { return nil, errBridgeNoIP } for _, cidr := range netdev.CIDRs { if subnet.Contains(cidr.IP) { return cidr.IP, nil } } // None in the required subnet; just return the first one return netdev.CIDRs[0].IP, nil }
// isCidrMatch tests if a given IP is in any of a given set of CIDR subnets. func isCidrMatch(ip *net.IP, subnets []string) (bool, error) { var cidr *net.IPNet var err error for _, subnet := range subnets { _, cidr, err = net.ParseCIDR(subnet) if err != nil { return false, err } if cidr.Contains(*ip) { return true, nil } } return false, nil }
// ParseIPRange creates an IPRange object based on the provided string // representing the range. The string for a range is in the form of // "192.168.1.1-100", to specify a range of IPs from 192.168.1.1 to // 192.168.1.100. The string can also contain a network mask, such as // "192.168.1.1-100/24". Strings can span over multiple octets, such as // "192.168.1.1-2.1", and a range can also be just a single IP. An error will be // returned if it fails to parse the IPs, if the end IP isn't after the start // IP, and if a network mask is given, it will error if the mask is in valid, or // the range does not fall within the bounds of the provided mask. func ParseIPRange(s string) (*IPRange, error) { ipr := &IPRange{} // check if the string contains a network mask if strings.Contains(s, "/") { p := strings.Split(s, "/") if len(p) != 2 { return nil, fmt.Errorf("expected only one '/' within the provided string") } s = p[0] maskBits, err := strconv.Atoi(p[1]) if err != nil { return nil, fmt.Errorf("failed to parse the network mask: %v", err) } ipr.Mask = net.CIDRMask(maskBits, 32) } // parse out the dash between the start-end IP portions ips := strings.Split(s, "-") if len(ips) > 2 { return nil, fmt.Errorf("unexpected number of IPs specified in the provided string") } ipr.Start = net.ParseIP(ips[0]) if len(ips) > 1 { ipr.End = net.ParseIP(spliceIP(ips[0], ips[1])) } else { ipr.End = ipr.Start } // ensure the end is after the start if bytes.Compare([]byte(ipr.End), []byte(ipr.Start)) < 0 { return nil, fmt.Errorf("the end of the range cannot be less than the start of the range") } // if a subnet was given, then ensure the IPs are within it if len(ipr.Mask) > 0 { ipnet := net.IPNet{ IP: ipr.Start, Mask: ipr.Mask, } if !ipnet.Contains(ipr.End) { return nil, fmt.Errorf("the provided IP ranges are not within the provided network mask") } } return ipr, nil }
func (e *Equipment) ListByNetwork(network net.IPNet) ([]Device, error) { devices, err := e.List() if err != nil { return nil, err } res := make([]Device, 0, len(devices)) for _, d := range devices { if !network.Contains(d.IP) { continue } res = append(res, d) } return res, nil }
func (oc *OsdnController) validateNetworkConfig(clusterNetwork, serviceNetwork *net.IPNet) error { // TODO: Instead of hardcoding 'tun0' and 'lbr0', get it from common place. // This will ensure both the kube/multitenant scripts and master validations use the same name. hostIPNets, err := netutils.GetHostIPNetworks([]string{"tun0", "lbr0"}) if err != nil { return err } errList := []error{} // Ensure cluster and service network don't overlap with host networks for _, ipNet := range hostIPNets { if ipNet.Contains(clusterNetwork.IP) { errList = append(errList, fmt.Errorf("Error: Cluster IP: %s conflicts with host network: %s", clusterNetwork.IP.String(), ipNet.String())) } if clusterNetwork.Contains(ipNet.IP) { errList = append(errList, fmt.Errorf("Error: Host network with IP: %s conflicts with cluster network: %s", ipNet.IP.String(), clusterNetwork.String())) } if ipNet.Contains(serviceNetwork.IP) { errList = append(errList, fmt.Errorf("Error: Service IP: %s conflicts with host network: %s", serviceNetwork.String(), ipNet.String())) } if serviceNetwork.Contains(ipNet.IP) { errList = append(errList, fmt.Errorf("Error: Host network with IP: %s conflicts with service network: %s", ipNet.IP.String(), serviceNetwork.String())) } } // Ensure each host subnet is within the cluster network subnets, err := oc.Registry.GetSubnets() if err != nil { return fmt.Errorf("Error in initializing/fetching subnets: %v", err) } for _, sub := range subnets { subnetIP, _, err := net.ParseCIDR(sub.Subnet) if err != nil { errList = append(errList, fmt.Errorf("Failed to parse network address: %s", sub.Subnet)) continue } if !clusterNetwork.Contains(subnetIP) { errList = append(errList, fmt.Errorf("Error: Existing node subnet: %s is not part of cluster network: %s", sub.Subnet, clusterNetwork.String())) } } // Ensure each service is within the services network services, err := oc.Registry.GetServices() if err != nil { return err } for _, svc := range services { if !serviceNetwork.Contains(net.ParseIP(svc.Spec.ClusterIP)) { errList = append(errList, fmt.Errorf("Error: Existing service with IP: %s is not part of service network: %s", svc.Spec.ClusterIP, serviceNetwork.String())) } } return kerrors.NewAggregate(errList) }
func (dynamicSubnetSelector) SelectSubnet(dynamic *net.IPNet, existing []*net.IPNet) (*net.IPNet, error) { exists := make(map[string]bool) for _, e := range existing { exists[e.String()] = true } min := dynamic.IP mask := net.CIDRMask(30, 32) // /30 for ip := min; dynamic.Contains(ip); ip = next(ip) { subnet := &net.IPNet{ip, mask} ip = next(next(next(ip))) if dynamic.Contains(ip) && !exists[subnet.String()] { return subnet, nil } } return nil, ErrInsufficientSubnets }
// Release allows releasing the address from the specified address space func (a *Allocator) Release(addrSpace AddressSpace, address net.IP) { var ( space *bitseq.Handle sub *net.IPNet ) if address == nil { log.Debugf("Requested to remove nil address from address space %s", addrSpace) return } ver := getAddressVersion(address) if ver == v4 { address = address.To4() } // Find the subnet containing the address for _, subKey := range a.getSubnetList(addrSpace, ver) { sub = subKey.canonicalChildSubnet() if sub.Contains(address) { a.Lock() space = a.addresses[subKey] a.Unlock() break } } if space == nil { log.Debugf("Could not find subnet on address space %s containing %s on release", addrSpace, address.String()) return } // Retrieve correspondent ordinal in the subnet hostPart, err := types.GetHostPartIP(address, sub.Mask) if err != nil { log.Warnf("Failed to release address %s on address space %s because of internal error: %v", address.String(), addrSpace, err) return } ordinal := ipToUint32(hostPart) // Release it if err := space.Unset(ordinal); err != nil { log.Warnf("Failed to release address %s on address space %s because of internal error: %v", address.String(), addrSpace, err) } }
func New(ipNet *net.IPNet) *RealNetworkPool { pool := []*network.Network{} _, startNet, err := net.ParseCIDR(ipNet.IP.String() + "/30") if err != nil { panic(err) } for subnet := startNet; ipNet.Contains(subnet.IP); subnet = nextSubnet(subnet) { pool = append(pool, network.New(subnet)) } return &RealNetworkPool{ ipNet: ipNet, pool: pool, poolMutex: new(sync.Mutex), } }