Пример #1
0
    def intersection(self, other):
        """
        @param other: an IP set.

        @return: the intersection of this IP set and another as a new IP set.
            (IP addresses and subnets common to both sets).
        """
        cidr_list = []

        #   Separate IPv4 from IPv6.
        l_ipv4, l_ipv6 = partition_ips(self._cidrs)
        r_ipv4, r_ipv6 = partition_ips(other._cidrs)

        #   Process IPv4.
        l_ipv4_iset = _IntSet(*[(c.first, c.last) for c in l_ipv4])
        r_ipv4_iset = _IntSet(*[(c.first, c.last) for c in r_ipv4])

        ipv4_result = l_ipv4_iset & r_ipv4_iset

        for start, end in list(ipv4_result._ranges):
            cidrs = iprange_to_cidrs(IPAddress(start, 4), IPAddress(end-1, 4))
            cidr_list.extend(cidrs)

        #   Process IPv6.
        l_ipv6_iset = _IntSet(*[(c.first, c.last) for c in l_ipv6])
        r_ipv6_iset = _IntSet(*[(c.first, c.last) for c in r_ipv6])

        ipv6_result = l_ipv6_iset & r_ipv6_iset

        for start, end in list(ipv6_result._ranges):
            cidrs = iprange_to_cidrs(IPAddress(start, 6), IPAddress(end-1, 6))
            cidr_list.extend(cidrs)

        return IPSet(cidr_list)
Пример #2
0
    def difference(self, other):
        """
        @param other: an IP set.

        @return: the difference between this IP set and another as a new IP
            set (all IP addresses and subnets that are in this IP set but
            not found in the other.)
        """
        cidr_list = []

        #   Separate IPv4 from IPv6.
        l_ipv4, l_ipv6 = partition_ips(self._cidrs)
        r_ipv4, r_ipv6 = partition_ips(other._cidrs)

        #   Process IPv4.
        l_ipv4_iset = _IntSet(*[(c.first, c.last) for c in l_ipv4])
        r_ipv4_iset = _IntSet(*[(c.first, c.last) for c in r_ipv4])

        ipv4_result = l_ipv4_iset - r_ipv4_iset

        for start, end in list(ipv4_result._ranges):
            cidrs = iprange_to_cidrs(IPAddress(start, 4), IPAddress(end-1, 4))
            cidr_list.extend(cidrs)

        #   Process IPv6.
        l_ipv6_iset = _IntSet(*[(c.first, c.last) for c in l_ipv6])
        r_ipv6_iset = _IntSet(*[(c.first, c.last) for c in r_ipv6])

        ipv6_result = l_ipv6_iset - r_ipv6_iset

        for start, end in list(ipv6_result._ranges):
            cidrs = iprange_to_cidrs(IPAddress(start, 6), IPAddress(end-1, 6))
            cidr_list.extend(cidrs)

        return IPSet(cidr_list)
Пример #3
0
Файл: sets.py Проект: embr/nonce
    def symmetric_difference(self, other):
        """
        :param other: an IP set.

        :return: the symmetric difference of this IP set and another as a new
            IP set (all IP addresses and subnets that are in exactly one
            of the sets).
        """
        cidr_list = []

        #   Separate IPv4 from IPv6.
        l_ipv4, l_ipv6 = partition_ips(self._cidrs)
        r_ipv4, r_ipv6 = partition_ips(other._cidrs)

        #   Process IPv4.
        l_ipv4_iset = _IntSet(*[(c.first, c.last) for c in l_ipv4])
        r_ipv4_iset = _IntSet(*[(c.first, c.last) for c in r_ipv4])

        ipv4_result = l_ipv4_iset ^ r_ipv4_iset

        for start, end in list(ipv4_result._ranges):
            cidrs = iprange_to_cidrs(IPAddress(start, 4), IPAddress(end - 1, 4))
            cidr_list.extend(cidrs)

        #   Process IPv6.
        l_ipv6_iset = _IntSet(*[(c.first, c.last) for c in l_ipv6])
        r_ipv6_iset = _IntSet(*[(c.first, c.last) for c in r_ipv6])

        ipv6_result = l_ipv6_iset ^ r_ipv6_iset

        for start, end in list(ipv6_result._ranges):
            cidrs = iprange_to_cidrs(IPAddress(start, 6), IPAddress(end - 1, 6))
            cidr_list.extend(cidrs)

        return IPSet(cidr_list)
Пример #4
0
    def __init__(self, iterable=None, flags=0):
        """
        Constructor.

        :param iterable: (optional) an iterable containing IP addresses and
            subnets.

        :param flags: decides which rules are applied to the interpretation
            of the addr value. See the netaddr.core namespace documentation
            for supported constant values.

        """
        if isinstance(iterable, IPNetwork):
            self._cidrs = {iterable.cidr: True}
        elif isinstance(iterable, IPRange):
            self._cidrs = dict.fromkeys(
                iprange_to_cidrs(iterable[0], iterable[-1]), True)
        elif isinstance(iterable, IPSet):
            self._cidrs = dict.fromkeys(iterable.iter_cidrs(), True)
        else:
            self._cidrs = {}
            if iterable is not None:
                mergeable = []
                for addr in iterable:
                    if isinstance(addr, _int_type):
                        addr = IPAddress(addr, flags=flags)
                    mergeable.append(addr)

                for cidr in cidr_merge(mergeable):
                    self._cidrs[cidr] = True
Пример #5
0
    def __init__(self, iterable=None, flags=0):
        """
        Constructor.

        :param iterable: (optional) an iterable containing IP addresses and
            subnets.

        :param flags: decides which rules are applied to the interpretation
            of the addr value. See the netaddr.core namespace documentation
            for supported constant values.

        """
        if isinstance(iterable, IPNetwork):
            self._cidrs = {iterable.cidr: True}
        elif isinstance(iterable, IPRange):
            self._cidrs = dict.fromkeys(
                iprange_to_cidrs(iterable[0], iterable[-1]), True)
        elif isinstance(iterable, IPSet):
            self._cidrs = dict.fromkeys(iterable.iter_cidrs(), True)
        else:
            self._cidrs = {}
            if iterable is not None:
                mergeable = []
                for addr in iterable:
                    if isinstance(addr, _int_type):
                        addr = IPAddress(addr, flags=flags)
                    mergeable.append(addr)

                for cidr in cidr_merge(mergeable):
                    self._cidrs[cidr] = True
Пример #6
0
    def add(self, addr, flags=0):
        """
        Adds an IP address or subnet or IPRange to this IP set. Has no effect if
        it is already present.

        Note that where possible the IP address or subnet is merged with other
        members of the set to form more concise CIDR blocks.

        :param addr: An IP address or subnet in either string or object form, or
            an IPRange object.

        :param flags: decides which rules are applied to the interpretation
            of the addr value. See the netaddr.core namespace documentation
            for supported constant values.

        """
        if isinstance(addr, IPRange):
            new_cidrs = dict.fromkeys(iprange_to_cidrs(addr[0], addr[-1]),
                                      True)
            self._cidrs.update(new_cidrs)
            self.compact()
            return
        if isinstance(addr, IPNetwork):
            # Networks like 10.1.2.3/8 need to be normalized to 10.0.0.0/8
            addr = addr.cidr
        elif isinstance(addr, _int_type):
            addr = IPNetwork(IPAddress(addr, flags=flags))
        else:
            addr = IPNetwork(addr)

        self._cidrs[addr] = True
        self._compact_single_network(addr)
Пример #7
0
    def add(self, addr, flags=0):
        """
        Adds an IP address or subnet or IPRange to this IP set. Has no effect if
        it is already present.

        Note that where possible the IP address or subnet is merged with other
        members of the set to form more concise CIDR blocks.

        :param addr: An IP address or subnet in either string or object form, or
            an IPRange object.

        :param flags: decides which rules are applied to the interpretation
            of the addr value. See the netaddr.core namespace documentation
            for supported constant values.

        """
        if isinstance(addr, IPRange):
            new_cidrs = dict.fromkeys(
                iprange_to_cidrs(addr[0], addr[-1]), True)
            self._cidrs.update(new_cidrs)
            self.compact()
            return
        if isinstance(addr, IPNetwork):
            # Networks like 10.1.2.3/8 need to be normalized to 10.0.0.0/8
            addr = addr.cidr
        elif isinstance(addr, _int_type):
            addr = IPNetwork(IPAddress(addr, flags=flags))
        else:
            addr = IPNetwork(addr)

        self._cidrs[addr] = True
        self._compact_single_network(addr)
Пример #8
0
def glob_to_cidrs(ipglob):
    """
    A function that accepts a glob-style IP range and returns a list of one
    or more IP CIDRs that exactly matches it.

    :param ipglob: an IP address range in a glob-style format.

    :return: a list of one or more IP objects.
    """
    return iprange_to_cidrs(*glob_to_iptuple(ipglob))
Пример #9
0
def glob_to_cidrs(ipglob):
    """
    A function that accepts a glob-style IP range and returns a list of one
    or more IP CIDRs that exactly matches it.

    :param ipglob: an IP address range in a glob-style format.

    :return: a list of one or more IP objects.
    """
    return iprange_to_cidrs(*glob_to_iptuple(ipglob))
Пример #10
0
    def remove(self, addr, flags=0):
        """
        Removes an IP address or subnet or IPRange from this IP set. Does
        nothing if it is not already a member.

        Note that this method behaves more like discard() found in regular
        Python sets because it doesn't raise KeyError exceptions if the
        IP address or subnet is question does not exist. It doesn't make sense
        to fully emulate that behaviour here as IP sets contain groups of
        individual IP addresses as individual set members using IPNetwork
        objects.

        :param addr: An IP address or subnet, or an IPRange.

        :param flags: decides which rules are applied to the interpretation
            of the addr value. See the netaddr.core namespace documentation
            for supported constant values.

        """
        if isinstance(addr, IPRange):
            cidrs = iprange_to_cidrs(addr[0], addr[-1])
            for cidr in cidrs:
                self.remove(cidr)
            return

        if isinstance(addr, _int_type):
            addr = IPAddress(addr, flags=flags)
        else:
            addr = IPNetwork(addr)

        #   This add() is required for address blocks provided that are larger
        #   than blocks found within the set but have overlaps. e.g. :-
        #
        #   >>> IPSet(['192.0.2.0/24']).remove('192.0.2.0/23')
        #   IPSet([])
        #
        self.add(addr)

        remainder = None
        matching_cidr = None

        #   Search for a matching CIDR and exclude IP from it.
        for cidr in self._cidrs:
            if addr in cidr:
                remainder = cidr_exclude(cidr, addr)
                matching_cidr = cidr
                break

        #   Replace matching CIDR with remaining CIDR elements.
        if remainder is not None:
            del self._cidrs[matching_cidr]
            for cidr in remainder:
                self._cidrs[cidr] = True
Пример #11
0
    def remove(self, addr, flags=0):
        """
        Removes an IP address or subnet or IPRange from this IP set. Does
        nothing if it is not already a member.

        Note that this method behaves more like discard() found in regular
        Python sets because it doesn't raise KeyError exceptions if the
        IP address or subnet is question does not exist. It doesn't make sense
        to fully emulate that behaviour here as IP sets contain groups of
        individual IP addresses as individual set members using IPNetwork
        objects.

        :param addr: An IP address or subnet, or an IPRange.

        :param flags: decides which rules are applied to the interpretation
            of the addr value. See the netaddr.core namespace documentation
            for supported constant values.

        """
        if isinstance(addr, IPRange):
            cidrs = iprange_to_cidrs(addr[0], addr[-1])
            for cidr in cidrs:
                self.remove(cidr)
            return

        if isinstance(addr, _int_type):
            addr = IPAddress(addr, flags=flags)
        else:
            addr = IPNetwork(addr)

        #   This add() is required for address blocks provided that are larger
        #   than blocks found within the set but have overlaps. e.g. :-
        #
        #   >>> IPSet(['192.0.2.0/24']).remove('192.0.2.0/23')
        #   IPSet([])
        #
        self.add(addr)

        remainder = None
        matching_cidr = None

        #   Search for a matching CIDR and exclude IP from it.
        for cidr in self._cidrs:
            if addr in cidr:
                remainder = cidr_exclude(cidr, addr)
                matching_cidr = cidr
                break

        #   Replace matching CIDR with remaining CIDR elements.
        if remainder is not None:
            del self._cidrs[matching_cidr]
            for cidr in remainder:
                self._cidrs[cidr] = True
Пример #12
0
    def difference(self, other):
        """
        :param other: an IP set.

        :return: the difference between this IP set and another as a new IP
            set (all IP addresses and subnets that are in this IP set but
            not found in the other.)
        """
        cidr_list = []

        #   Separate IPv4 from IPv6.
        l_ipv4, l_ipv6 = partition_ips(self._cidrs)
        r_ipv4, r_ipv6 = partition_ips(other._cidrs)

        #   Process IPv4.
        l_ipv4_iset = _IntSet(*[(c.first, c.last) for c in l_ipv4])
        r_ipv4_iset = _IntSet(*[(c.first, c.last) for c in r_ipv4])

        ipv4_result = l_ipv4_iset - r_ipv4_iset

        for start, end in ipv4_result._ranges:
            cidrs = iprange_to_cidrs(IPAddress(start, 4),
                                     IPAddress(end - 1, 4))
            cidr_list.extend(cidrs)

        #   Process IPv6.
        l_ipv6_iset = _IntSet(*[(c.first, c.last) for c in l_ipv6])
        r_ipv6_iset = _IntSet(*[(c.first, c.last) for c in r_ipv6])

        ipv6_result = l_ipv6_iset - r_ipv6_iset

        for start, end in ipv6_result._ranges:
            cidrs = iprange_to_cidrs(IPAddress(start, 6),
                                     IPAddress(end - 1, 6))
            cidr_list.extend(cidrs)

        result = IPSet()
        # None of these CIDRs can be compacted, so skip that operation.
        result._cidrs = dict.fromkeys(cidr_list, True)
        return result
Пример #13
0
    def difference(self, other):
        """
        :param other: an IP set.

        :return: the difference between this IP set and another as a new IP
            set (all IP addresses and subnets that are in this IP set but
            not found in the other.)
        """
        result_ranges = []
        result_cidrs = {}

        own_nets = sorted(self._cidrs)
        other_nets = sorted(other._cidrs)
        own_idx = 0
        other_idx = 0
        own_len = len(own_nets)
        other_len = len(other_nets)
        while own_idx < own_len and other_idx < other_len:
            own_cur = own_nets[own_idx]
            other_cur = other_nets[other_idx]

            if own_cur == other_cur:
                own_idx += 1
                other_idx += 1
            elif own_cur in other_cur:
                own_idx += 1
            elif other_cur in own_cur:
                other_idx = _subtract(own_cur, other_nets, other_idx,
                                      result_ranges)
                own_idx += 1
            else:
                # own_cur and other_cur have nothing in common
                if own_cur < other_cur:
                    result_cidrs[own_cur] = True
                    own_idx += 1
                else:
                    other_idx += 1

        # If the above loop terminated because it processed all cidrs of
        # "other", then any remaining cidrs in self must be part of the result.
        while own_idx < own_len:
            result_cidrs[own_nets[own_idx]] = True
            own_idx += 1

        for start, stop in _iter_merged_ranges(result_ranges):
            for cidr in iprange_to_cidrs(start, stop):
                result_cidrs[cidr] = True

        result = IPSet()
        result._cidrs = result_cidrs
        return result
Пример #14
0
    def difference(self, other):
        """
        :param other: an IP set.

        :return: the difference between this IP set and another as a new IP
            set (all IP addresses and subnets that are in this IP set but
            not found in the other.)
        """
        result_ranges = []
        result_cidrs = {}

        own_nets = sorted(self._cidrs)
        other_nets = sorted(other._cidrs)
        own_idx = 0
        other_idx = 0
        own_len = len(own_nets)
        other_len = len(other_nets)
        while own_idx < own_len and other_idx < other_len:
            own_cur = own_nets[own_idx]
            other_cur = other_nets[other_idx]

            if own_cur == other_cur:
                own_idx += 1
                other_idx += 1
            elif own_cur in other_cur:
                own_idx += 1
            elif other_cur in own_cur:
                other_idx = _subtract(own_cur, other_nets, other_idx,
                                      result_ranges)
                own_idx += 1
            else:
                # own_cur and other_cur have nothing in common
                if own_cur < other_cur:
                    result_cidrs[own_cur] = True
                    own_idx += 1
                else:
                    other_idx += 1

        # If the above loop terminated because it processed all cidrs of
        # "other", then any remaining cidrs in self must be part of the result.
        while own_idx < own_len:
            result_cidrs[own_nets[own_idx]] = True
            own_idx += 1

        for start, stop in _iter_merged_ranges(result_ranges):
            for cidr in iprange_to_cidrs(start, stop):
                result_cidrs[cidr] = True

        result = IPSet()
        result._cidrs = result_cidrs
        return result
Пример #15
0
    def difference(self, other):
        """
        :param other: an IP set.

        :return: the difference between this IP set and another as a new IP
            set (all IP addresses and subnets that are in this IP set but
            not found in the other.)
        """
        cidr_list = []

        #   Separate IPv4 from IPv6.
        l_ipv4, l_ipv6 = partition_ips(self._cidrs)
        r_ipv4, r_ipv6 = partition_ips(other._cidrs)

        #   Process IPv4.
        l_ipv4_iset = _IntSet(*[(c.first, c.last) for c in l_ipv4])
        r_ipv4_iset = _IntSet(*[(c.first, c.last) for c in r_ipv4])

        ipv4_result = l_ipv4_iset - r_ipv4_iset

        for start, end in ipv4_result._ranges:
            cidrs = iprange_to_cidrs(IPAddress(start, 4), IPAddress(end-1, 4))
            cidr_list.extend(cidrs)

        #   Process IPv6.
        l_ipv6_iset = _IntSet(*[(c.first, c.last) for c in l_ipv6])
        r_ipv6_iset = _IntSet(*[(c.first, c.last) for c in r_ipv6])

        ipv6_result = l_ipv6_iset - r_ipv6_iset

        for start, end in ipv6_result._ranges:
            cidrs = iprange_to_cidrs(IPAddress(start, 6), IPAddress(end-1, 6))
            cidr_list.extend(cidrs)

        result = IPSet()
        # None of these CIDRs can be compacted, so skip that operation.
        result._cidrs = dict.fromkeys(cidr_list, True)
        return result
Пример #16
0
    def symmetric_difference(self, other):
        """
        :param other: an IP set.

        :return: the symmetric difference of this IP set and another as a new
            IP set (all IP addresses and subnets that are in exactly one
            of the sets).
        """
        cidr_list = []

        #   Separate IPv4 from IPv6.
        l_ipv4, l_ipv6 = partition_ips(self._cidrs)
        r_ipv4, r_ipv6 = partition_ips(other._cidrs)

        #   Process IPv4.
        l_ipv4_iset = _IntSet(*[(c.first, c.last) for c in l_ipv4])
        r_ipv4_iset = _IntSet(*[(c.first, c.last) for c in r_ipv4])

        ipv4_result = l_ipv4_iset ^ r_ipv4_iset

        for start, end in list(ipv4_result._ranges):
            cidrs = iprange_to_cidrs(IPAddress(start, 4),
                                     IPAddress(end - 1, 4))
            cidr_list.extend(cidrs)

        #   Process IPv6.
        l_ipv6_iset = _IntSet(*[(c.first, c.last) for c in l_ipv6])
        r_ipv6_iset = _IntSet(*[(c.first, c.last) for c in r_ipv6])

        ipv6_result = l_ipv6_iset ^ r_ipv6_iset

        for start, end in list(ipv6_result._ranges):
            cidrs = iprange_to_cidrs(IPAddress(start, 6),
                                     IPAddress(end - 1, 6))
            cidr_list.extend(cidrs)

        return IPSet(cidr_list)
Пример #17
0
    def difference(self, other):
        """
        @param other: an IP set.

        @return: the difference between this IP set and another as a new IP
            set (all IP addresses and subnets that are in this IP set but
            not found in the other.)
        """
        cidr_list = []

        #   Separate IPv4 from IPv6.
        l_ipv4, l_ipv6 = partition_ips(self._cidrs)
        r_ipv4, r_ipv6 = partition_ips(other._cidrs)

        #   Process IPv4.
        l_ipv4_iset = _IntSet(*[(c.first, c.last) for c in l_ipv4])
        r_ipv4_iset = _IntSet(*[(c.first, c.last) for c in r_ipv4])

        ipv4_result = l_ipv4_iset - r_ipv4_iset

        for start, end in list(ipv4_result._ranges):
            cidrs = iprange_to_cidrs(IPAddress(start, 4),
                                     IPAddress(end - 1, 4))
            cidr_list.extend(cidrs)

        #   Process IPv6.
        l_ipv6_iset = _IntSet(*[(c.first, c.last) for c in l_ipv6])
        r_ipv6_iset = _IntSet(*[(c.first, c.last) for c in r_ipv6])

        ipv6_result = l_ipv6_iset - r_ipv6_iset

        for start, end in list(ipv6_result._ranges):
            cidrs = iprange_to_cidrs(IPAddress(start, 6),
                                     IPAddress(end - 1, 6))
            cidr_list.extend(cidrs)

        return IPSet(cidr_list)
Пример #18
0
    def intersection(self, other):
        """
        :param other: an IP set.

        :return: the intersection of this IP set and another as a new IP set.
            (IP addresses and subnets common to both sets).
        """
        cidr_list = []

        #   Separate IPv4 from IPv6.
        l_ipv4, l_ipv6 = partition_ips(self._cidrs)
        r_ipv4, r_ipv6 = partition_ips(other._cidrs)

        #   Process IPv4.
        l_ipv4_iset = _IntSet(*[(c.first, c.last) for c in l_ipv4])
        r_ipv4_iset = _IntSet(*[(c.first, c.last) for c in r_ipv4])

        ipv4_result = l_ipv4_iset & r_ipv4_iset

        for start, end in list(ipv4_result._ranges):
            cidrs = iprange_to_cidrs(IPAddress(start, 4),
                                     IPAddress(end - 1, 4))
            cidr_list.extend(cidrs)

        #   Process IPv6.
        l_ipv6_iset = _IntSet(*[(c.first, c.last) for c in l_ipv6])
        r_ipv6_iset = _IntSet(*[(c.first, c.last) for c in r_ipv6])

        ipv6_result = l_ipv6_iset & r_ipv6_iset

        for start, end in list(ipv6_result._ranges):
            cidrs = iprange_to_cidrs(IPAddress(start, 6),
                                     IPAddress(end - 1, 6))
            cidr_list.extend(cidrs)

        return IPSet(cidr_list)
Пример #19
0
    def symmetric_difference(self, other):
        """
        :param other: an IP set.

        :return: the symmetric difference of this IP set and another as a new
            IP set (all IP addresses and subnets that are in exactly one
            of the sets).
        """
        # In contrast to intersection() and difference(), we cannot construct
        # the result_cidrs easily. Some cidrs may have to be merged, e.g. for
        # IPSet(["10.0.0.0/32"]).symmetric_difference(IPSet(["10.0.0.1/32"])).
        result_ranges = []

        own_nets = sorted(self._cidrs)
        other_nets = sorted(other._cidrs)
        own_idx = 0
        other_idx = 0
        own_len = len(own_nets)
        other_len = len(other_nets)
        while own_idx < own_len and other_idx < other_len:
            own_cur = own_nets[own_idx]
            other_cur = other_nets[other_idx]

            if own_cur == other_cur:
                own_idx += 1
                other_idx += 1
            elif own_cur in other_cur:
                own_idx = _subtract(other_cur, own_nets, own_idx, result_ranges)
                other_idx += 1
            elif other_cur in own_cur:
                other_idx = _subtract(own_cur, other_nets, other_idx, result_ranges)
                own_idx += 1
            else:
                # own_cur and other_cur have nothing in common
                if own_cur < other_cur:
                    result_ranges.append((own_cur._module.version,
                                          own_cur.first, own_cur.last))
                    own_idx += 1
                else:
                    result_ranges.append((other_cur._module.version,
                                          other_cur.first, other_cur.last))
                    other_idx += 1

        # If the above loop terminated because it processed all cidrs of
        # "other", then any remaining cidrs in self must be part of the result.
        while own_idx < own_len:
            own_cur = own_nets[own_idx]
            result_ranges.append((own_cur._module.version,
                                  own_cur.first, own_cur.last))
            own_idx += 1

        # If the above loop terminated because it processed all cidrs of
        # self, then any remaining cidrs in "other" must be part of the result.
        while other_idx < other_len:
            other_cur = other_nets[other_idx]
            result_ranges.append((other_cur._module.version,
                                  other_cur.first, other_cur.last))
            other_idx += 1

        result = IPSet()
        for start, stop in _iter_merged_ranges(result_ranges):
            cidrs = iprange_to_cidrs(start, stop)
            for cidr in cidrs:
                result._cidrs[cidr] = True
        return result
Пример #20
0
def iprange_to_globs(start, end):
    """
    A function that accepts an arbitrary start and end IP address or subnet
    and returns one or more glob-style IP ranges.

    :param start: the start IP address or subnet.

    :param end: the end IP address or subnet.

    :return: a list containing one or more IP globs.
    """
    start = IPAddress(start)
    end = IPAddress(end)

    if start.version != 4 and end.version != 4:
        raise AddrConversionError('IP glob ranges only support IPv4!')

    def _iprange_to_glob(lb, ub):
        #   Internal function to process individual IP globs.
        t1 = [int(_) for _ in str(lb).split('.')]
        t2 = [int(_) for _ in str(ub).split('.')]

        tokens = []

        seen_hyphen = False
        seen_asterisk = False

        for i in range(4):
            if t1[i] == t2[i]:
                #   A normal octet.
                tokens.append(str(t1[i]))
            elif (t1[i] == 0) and (t2[i] == 255):
                #   An asterisk octet.
                tokens.append('*')
                seen_asterisk = True
            else:
                #   Create a hyphenated octet - only one allowed per IP glob.
                if not seen_asterisk:
                    if not seen_hyphen:
                        tokens.append('%s-%s' % (t1[i], t2[i]))
                        seen_hyphen = True
                    else:
                        raise AddrConversionError('only 1 hyphenated octet' \
                            ' per IP glob allowed!')
                else:
                    raise AddrConversionError("asterisks are not allowed' \
                        ' before hyphenated octets!")

        return '.'.join(tokens)

    globs = []

    try:
        #   IP range can be represented by a single glob.
        ipglob = _iprange_to_glob(start, end)
        if not valid_glob(ipglob):
            #TODO: this is a workaround, it is produces non-optimal but valid
            #TODO: glob conversions. Fix inner function so that is always
            #TODO: produces a valid glob.
            raise AddrConversionError('invalid ip glob created')
        globs.append(ipglob)
    except AddrConversionError:
        #   Break IP range up into CIDRs before conversion to globs.
        #
        #TODO: this is still not completely optimised but is good enough
        #TODO: for the moment.
        #
        for cidr in iprange_to_cidrs(start, end):
            ipglob = _iprange_to_glob(cidr[0], cidr[-1])
            globs.append(ipglob)

    return globs
Пример #21
0
def iprange_to_globs(start, end):
    """
    A function that accepts an arbitrary start and end IP address or subnet
    and returns one or more glob-style IP ranges.

    :param start: the start IP address or subnet.

    :param end: the end IP address or subnet.

    :return: a list containing one or more IP globs.
    """
    start = IPAddress(start)
    end = IPAddress(end)

    if start.version != 4 and end.version != 4:
        raise AddrConversionError('IP glob ranges only support IPv4!')

    def _iprange_to_glob(lb, ub):
        #   Internal function to process individual IP globs.
        t1 = [int(_) for _ in str(lb).split('.')]
        t2 = [int(_) for _ in str(ub).split('.')]

        tokens = []

        seen_hyphen = False
        seen_asterisk = False

        for i in range(4):
            if t1[i] == t2[i]:
                #   A normal octet.
                tokens.append(str(t1[i]))
            elif (t1[i] == 0) and (t2[i] == 255):
                #   An asterisk octet.
                tokens.append('*')
                seen_asterisk = True
            else:
                #   Create a hyphenated octet - only one allowed per IP glob.
                if not seen_asterisk:
                    if not seen_hyphen:
                        tokens.append('%s-%s' % (t1[i], t2[i]))
                        seen_hyphen = True
                    else:
                        raise AddrConversionError(
                            'only 1 hyphenated octet per IP glob allowed!')
                else:
                    raise AddrConversionError(
                        "asterisks are not allowed before hyphenated octets!")

        return '.'.join(tokens)

    globs = []

    try:
        #   IP range can be represented by a single glob.
        ipglob = _iprange_to_glob(start, end)
        if not valid_glob(ipglob):
            #TODO: this is a workaround, it is produces non-optimal but valid
            #TODO: glob conversions. Fix inner function so that is always
            #TODO: produces a valid glob.
            raise AddrConversionError('invalid ip glob created')
        globs.append(ipglob)
    except AddrConversionError:
        #   Break IP range up into CIDRs before conversion to globs.
        #
        #TODO: this is still not completely optimised but is good enough
        #TODO: for the moment.
        #
        for cidr in iprange_to_cidrs(start, end):
            ipglob = _iprange_to_glob(cidr[0], cidr[-1])
            globs.append(ipglob)

    return globs
Пример #22
0
    def symmetric_difference(self, other):
        """
        :param other: an IP set.

        :return: the symmetric difference of this IP set and another as a new
            IP set (all IP addresses and subnets that are in exactly one
            of the sets).
        """
        # In contrast to intersection() and difference(), we cannot construct
        # the result_cidrs easily. Some cidrs may have to be merged, e.g. for
        # IPSet(["10.0.0.0/32"]).symmetric_difference(IPSet(["10.0.0.1/32"])).
        result_ranges = []

        own_nets = sorted(self._cidrs)
        other_nets = sorted(other._cidrs)
        own_idx = 0
        other_idx = 0
        own_len = len(own_nets)
        other_len = len(other_nets)
        while own_idx < own_len and other_idx < other_len:
            own_cur = own_nets[own_idx]
            other_cur = other_nets[other_idx]

            if own_cur == other_cur:
                own_idx += 1
                other_idx += 1
            elif own_cur in other_cur:
                own_idx = _subtract(other_cur, own_nets, own_idx,
                                    result_ranges)
                other_idx += 1
            elif other_cur in own_cur:
                other_idx = _subtract(own_cur, other_nets, other_idx,
                                      result_ranges)
                own_idx += 1
            else:
                # own_cur and other_cur have nothing in common
                if own_cur < other_cur:
                    result_ranges.append(
                        (own_cur._module.version, own_cur.first, own_cur.last))
                    own_idx += 1
                else:
                    result_ranges.append((other_cur._module.version,
                                          other_cur.first, other_cur.last))
                    other_idx += 1

        # If the above loop terminated because it processed all cidrs of
        # "other", then any remaining cidrs in self must be part of the result.
        while own_idx < own_len:
            own_cur = own_nets[own_idx]
            result_ranges.append(
                (own_cur._module.version, own_cur.first, own_cur.last))
            own_idx += 1

        # If the above loop terminated because it processed all cidrs of
        # self, then any remaining cidrs in "other" must be part of the result.
        while other_idx < other_len:
            other_cur = other_nets[other_idx]
            result_ranges.append(
                (other_cur._module.version, other_cur.first, other_cur.last))
            other_idx += 1

        result = IPSet()
        for start, stop in _iter_merged_ranges(result_ranges):
            cidrs = iprange_to_cidrs(start, stop)
            for cidr in cidrs:
                result._cidrs[cidr] = True
        return result