Esempio n. 1
0
def generate_new_cidr(allocated_subnets: List[str],
                      required_cidr_block_type: int) -> str:
    if required_cidr_block_type >= 32 or required_cidr_block_type < 8:
        raise NetmaskValueError("Invalid netmask for this operation.")

    free_subnets = get_free_subnets(allocated_subnets)

    # compare to the required subnet size and work with what is large enough
    free_subnets = [
        x for x in free_subnets if x.prefixlen <= required_cidr_block_type
    ]

    if len(free_subnets) == 0:
        raise Exception("Not enough space in network.")

    # allocate in smaller subnets before larger ones
    free_subnets.sort(key=lambda x: x.prefixlen, reverse=True)
    allocation_subnet = free_subnets[0]
    new_subnet = list(
        allocation_subnet.subnets(new_prefix=required_cidr_block_type))
    return str(new_subnet[0])
Esempio n. 2
0
def ipv4_address(addr: str) -> str:
    """
    Validate an IPv4 address.

    :param addr: IPv4 address
    :returns: IPv4 address
    :raises TypeError, AddressValueError or NetmaskValueError
    """
    if not isinstance(addr, str):
        raise TypeError("Invalid input, addr must be a string")
    else:
        addr = addr.strip()

    if addr == "":
        return addr

    if not netaddr.valid_ipv4(addr):
        raise AddressValueError("Invalid IPv4 address format (%s)" % addr)

    if netaddr.IPAddress(addr).is_netmask():
        raise NetmaskValueError("Invalid IPv4 host address (%s)" % addr)

    return addr
Esempio n. 3
0
def ipv4_address(addr: str) -> str:
    """
    Validate an IPv4 address.

    :param addr: IPv4 address
    :returns: IPv4 address
    :raises TypeError: Raised if ``addr`` is not a string.
    :raises AddressValueError: Raised in case ``addr`` is not a valid IPv4 address.
    :raises NetmaskValueError: Raised in case ``addr`` is not a valid IPv4 netmask.
    """
    if not isinstance(addr, str):
        raise TypeError("Invalid input, addr must be a string")
    addr = addr.strip()

    if addr == "":
        return addr

    if not netaddr.valid_ipv4(addr):
        raise AddressValueError("Invalid IPv4 address format (%s)" % addr)

    if netaddr.IPAddress(addr).is_netmask():
        raise NetmaskValueError("Invalid IPv4 host address (%s)" % addr)

    return addr
Esempio n. 4
0
def acl_with_wildcard_to_netmasks(address_str: str, wildcard_str: str):
    """
    Translates an ACL (address, wildcard) to a list of ip_network objects (address, netmask)
    :param address_str: IP address string (v4 or v6)
    :param wildcard_str: wildcard mask (v4 or v6)
    :return: list of IP networks

    E.G for address="172.18.161.2" and wildcard "0.1.2.7"
    it returns:
        [IPv4Network('172.18.161.0/29'), IPv4Network('172.18.163.0/29'),
        IPv4Network('172.19.161.0/29'), IPv4Network('172.19.163.0/29')]
    """

    ip_addr = ipaddress.ip_address(address_str)
    wildcard = ipaddress.ip_address(wildcard_str)

    if wildcard.version != ip_addr.version:
        raise ValueError(
            f"IP version mismtach: address_str({address_str}), wildcard_str({wildcard_str})"
        )

    # default values for v4
    _length = ipaddress.IPV4LENGTH
    _net_cls = ipaddress.IPv4Network
    if wildcard.version == 6:
        # values for v6
        _length = ipaddress.IPV6LENGTH
        _net_cls = ipaddress.IPv6Network

    mask_bits = [int(b) for b in format(int(wildcard), F"0{_length}b")]

    # We keep count of zero bits position (left-most is 0)
    dont_care_bits_index = [
        i for i, e in enumerate(reversed(mask_bits)) if e == 1
    ]

    # We count how many contiguous zeros are from left-most bit, and we will mask them with a netmask
    hostmask_length = 0
    for (pos, bit) in enumerate(dont_care_bits_index):
        if pos != bit:
            break
        hostmask_length += 1

    # We only keep the bits that can't be dealt with by a netmask and need to be expanded to cartesian product
    dont_care_to_expand_index = dont_care_bits_index[hostmask_length:]

    # reverse in order to have the final loop iterate last through high order bits
    dont_care_to_expand_index.reverse()

    if len(dont_care_to_expand_index) > MAX_DONT_CARE_BITS:
        raise NetmaskValueError(
            f"{wildcard_str} contains more than {MAX_DONT_CARE_BITS} non-contiguous wildcard bits"
        )

    ip_int_original = int(ip_addr)
    subnets = []
    for bits_values in itertools.product(
        (0, 1), repeat=len(dont_care_to_expand_index)):
        # enforce the bits_values in the IP address
        ip_int = ip_int_original
        for (index, val) in zip(dont_care_to_expand_index, bits_values):
            sb_mask = 1 << index
            if val:
                ip_int |= sb_mask
            else:
                ip_int &= ~sb_mask

        subnets.append(
            _net_cls((ip_int, _length - hostmask_length), strict=False))

    return subnets