コード例 #1
0
 def testSummarizeToAllSpace(self):
     nets = [
         ipaddr.IPv4Network('0.0.0.0/1'),
         ipaddr.IPv4Network('128.0.0.0/1'),
     ]
     random.shuffle(nets)
     result = summarizer.Summarize(nets)
     self.assertEquals(result, [(0, 0)])
コード例 #2
0
 def testSummarizeNoNetworks(self):
     nets = []
     for octet in range(0, 256):
         net = ipaddr.IPv4Network('192.' + str(255 - octet) + '.' +
                                  str(octet) + '.64/27')
         nets.append(net)
     random.shuffle(nets)
     result = summarizer.Summarize(nets)
     self.assertEqual(len(result), 256)
コード例 #3
0
 def testSummarizeAllNetworks(self):
     nets = []
     for octet in range(0, 256):
         net = ipaddr.IPv4Network('192.168.' + str(octet) + '.64/27')
         nets.append(net)
     random.shuffle(nets)
     result = summarizer.Summarize(nets)
     # summarizes to 192.168.0.64 / 255.255.0.224
     self.assertEquals(result, [(3232235584, 4294901984)])
コード例 #4
0
 def testSummarizeSomeNetworks(self):
     nets = [
         # continiously summarizable to one /25
         ipaddr.IPv4Network('192.168.0.0/27'),
         ipaddr.IPv4Network('192.168.0.32/27'),
         ipaddr.IPv4Network('192.168.0.64/27'),
         ipaddr.IPv4Network('192.168.0.96/27'),
         # discontiniously summarizable with above
         ipaddr.IPv4Network('128.168.0.0/25'),
         # not summarizable with above
         ipaddr.IPv4Network('10.0.0.0/8'),
     ]
     for octet in range(0, 256):
         net = ipaddr.IPv4Network('172.16.' + str(octet) + '.96/30')
         nets.append(net)
     random.shuffle(nets)
     result = summarizer.Summarize(nets)
     self.assertEquals(result, [(167772160, 4278190080),
                                (2158493696, 3221225344),
                                (2886729824, 4294902012)])
コード例 #5
0
ファイル: summarizer_test.py プロジェクト: yijxiang/capirca
    def testSummarizeDSMONetworks(self):
        fourth_octet = [
            2, 8, 20, 26, 28, 32, 40, 52, 58, 86, 130, 136, 148, 154, 156, 160,
            168, 180, 186, 214
        ]
        nets = list()

        for octet3 in range(56, 60):
            for octet4 in fourth_octet:
                nets.append(
                    ipaddr.IPv4Network('192.168.' + str(octet3) + '.' +
                                       str(octet4) + '/31'))

        result = summarizer.Summarize(nets)
        self.assertEquals(result, [(3232249858, 4294966398),
                                   (3232249888, 4294966398),
                                   (3232249908, 4294966398),
                                   (3232249942, 4294966398),
                                   (3232249864, 4294966366),
                                   (3232249876, 4294966390),
                                   (3232249882, 4294966366)])
コード例 #6
0
ファイル: juniper.py プロジェクト: yoshipaulbrophy/capirca
    def __str__(self):
        # Verify platform specific terms. Skip whole term if platform does not
        # match.
        if self.term.platform:
            if self._PLATFORM not in self.term.platform:
                return ''
        if self.term.platform_exclude:
            if self._PLATFORM in self.term.platform_exclude:
                return ''

        config = Config(indent=self._DEFAULT_INDENT)
        from_str = []
        # Don't render icmpv6 protocol terms under inet, or icmp under inet6
        if ((self.term_type == 'inet6' and 'icmp' in self.term.protocol) or
            (self.term_type == 'inet' and 'icmpv6' in self.term.protocol)):
            logging.debug(
                self.NO_AF_LOG_PROTO.substitute(term=self.term.name,
                                                proto=self.term.protocol,
                                                af=self.term_type))
            return ''

        # comment
        # this deals just fine with multi line comments, but we could probably
        # output them a little cleaner; do things like make sure the
        # len(output) < 80, etc. Note, if 'noverbose' is set for the filter, skip
        # all comment processing.
        if self.term.owner and not self.noverbose:
            self.term.comment.append('Owner: %s' % self.term.owner)
        if self.term.comment and not self.noverbose:
            config.Append('/*')
            for comment in self.term.comment:
                for line in comment.split('\n'):
                    config.Append('** ' + line)
            config.Append('*/')

        # Term verbatim output - this will skip over normal term creation
        # code.  Warning generated from policy.py if appropriate.
        if self.term.verbatim:
            for next_term in self.term.verbatim:
                if next_term.value[0] == self._PLATFORM:
                    config.Append(str(next_term.value[1]), verbatim=True)
            return str(config)

        # Helper for per-address-family keywords.
        family_keywords = self._TERM_TYPE.get(self.term_type)

        # option
        # this is going to be a little ugly b/c there are a few little messed
        # up options we can deal with.
        if self.term.option:
            for opt in [str(x) for x in self.term.option]:
                # there should be a better way to search the array of protocols
                if opt.startswith('sample'):
                    self.extra_actions.append('sample')

                # only append tcp-established for option established when
                # tcp is the only protocol, otherwise other protos break on juniper
                elif opt.startswith('established'):
                    if self.term.protocol == ['tcp']:
                        if 'tcp-established;' not in from_str:
                            from_str.append(family_keywords['tcp-est'] + ';')

                # if tcp-established specified, but more than just tcp is included
                # in the protocols, raise an error
                elif opt.startswith('tcp-established'):
                    flag = family_keywords['tcp-est'] + ';'
                    if self.term.protocol == ['tcp']:
                        if flag not in from_str:
                            from_str.append(flag)
                    else:
                        raise TcpEstablishedWithNonTcp(
                            'tcp-established can only be used with tcp protocol in term %s'
                            % self.term.name)
                elif opt.startswith('rst'):
                    from_str.append('tcp-flags "rst";')
                elif opt.startswith('initial') and 'tcp' in self.term.protocol:
                    from_str.append('tcp-initial;')
                elif opt.startswith('first-fragment'):
                    from_str.append('first-fragment;')

                # we don't have a special way of dealing with this, so we output it and
                # hope the user knows what they're doing.
                else:
                    from_str.append('%s;' % opt)

        # term name
        config.Append('term %s {' % self.term.name)

        # a default action term doesn't have any from { clause
        has_match_criteria = (
            self.term.address or self.term.dscp_except or self.term.dscp_match
            or self.term.destination_address or self.term.destination_port
            or self.term.destination_prefix
            or self.term.destination_prefix_except or self.term.ether_type
            or self.term.flexible_match_range or self.term.forwarding_class
            or self.term.forwarding_class_except or self.term.hop_limit
            or self.term.next_ip or self.term.port or self.term.precedence
            or self.term.protocol or self.term.protocol_except
            or self.term.source_address or self.term.source_port
            or self.term.source_prefix or self.term.source_prefix_except
            or self.term.traffic_type)

        if has_match_criteria:
            config.Append('from {')

            term_af = self.AF_MAP.get(self.term_type)

            # address
            address = self.term.GetAddressOfVersion('address', term_af)
            if self.enable_dsmo:
                address = summarizer.Summarize(address)

            if address:
                config.Append('%s {' % family_keywords['addr'])
                for addr in address:
                    if self.enable_dsmo:
                        config.Append(
                            '%s/%s;' %
                            summarizer.ToDottedQuad(addr, nondsm=True))
                    else:
                        for comment in self._Comment(addr):
                            config.Append('%s' % comment)
                        config.Append('%s;' % addr)
                config.Append('}')
            elif self.term.address:
                logging.debug(
                    self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                   af=self.term_type))
                return ''

            # source address
            src_addr = self.term.GetAddressOfVersion('source_address', term_af)
            src_addr_ex = self.term.GetAddressOfVersion(
                'source_address_exclude', term_af)
            if self.enable_dsmo:
                src_addr = summarizer.Summarize(src_addr)
                src_addr_ex = summarizer.Summarize(src_addr_ex)
            else:
                src_addr, src_addr_ex = self._MinimizePrefixes(
                    src_addr, src_addr_ex)

            if src_addr:
                config.Append('%s {' % family_keywords['saddr'])
                for addr in src_addr:
                    if self.enable_dsmo:
                        config.Append(
                            '%s/%s;' %
                            summarizer.ToDottedQuad(addr, nondsm=True))
                    else:
                        for comment in self._Comment(addr):
                            config.Append('%s' % comment)
                        config.Append('%s;' % addr)
                for addr in src_addr_ex:
                    if self.enable_dsmo:
                        config.Append(
                            '%s/%s except;' %
                            summarizer.ToDottedQuad(addr, nondsm=True))
                    else:
                        for comment in self._Comment(addr, exclude=True):
                            config.Append('%s' % comment)
                        config.Append('%s except;' % addr)
                config.Append('}')
            elif self.term.source_address:
                logging.debug(
                    self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                   direction='source',
                                                   af=self.term_type))
                return ''

            # destination address
            dst_addr = self.term.GetAddressOfVersion('destination_address',
                                                     term_af)
            dst_addr_ex = self.term.GetAddressOfVersion(
                'destination_address_exclude', term_af)
            if self.enable_dsmo:
                dst_addr = summarizer.Summarize(dst_addr)
                dst_addr_ex = summarizer.Summarize(dst_addr_ex)
            else:
                dst_addr, dst_addr_ex = self._MinimizePrefixes(
                    dst_addr, dst_addr_ex)

            if dst_addr:
                config.Append('%s {' % family_keywords['daddr'])
                for addr in dst_addr:
                    if self.enable_dsmo:
                        config.Append(
                            '%s/%s;' %
                            summarizer.ToDottedQuad(addr, nondsm=True))
                    else:
                        for comment in self._Comment(addr):
                            config.Append('%s' % comment)
                        config.Append('%s;' % addr)
                for addr in dst_addr_ex:
                    if self.enable_dsmo:
                        config.Append(
                            '%s/%s except;' %
                            summarizer.ToDottedQuad(addr, nondsm=True))
                    else:
                        for comment in self._Comment(addr, exclude=True):
                            config.Append('%s' % comment)
                        config.Append('%s except;' % addr)
                config.Append('}')
            elif self.term.destination_address:
                logging.debug(
                    self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                   direction='destination',
                                                   af=self.term_type))
                return ''

            # forwarding-class
            if self.term.forwarding_class:
                config.Append('forwarding-class %s' %
                              self._Group(self.term.forwarding_class))

            # forwarding-class-except
            if self.term.forwarding_class_except:
                config.Append('forwarding-class-except %s' %
                              self._Group(self.term.forwarding_class_except))

            # source prefix <except> list
            if self.term.source_prefix or self.term.source_prefix_except:
                config.Append('source-prefix-list {')
                for pfx in self.term.source_prefix:
                    config.Append(pfx + ';')
                for epfx in self.term.source_prefix_except:
                    config.Append(epfx + ' except;')
                config.Append('}')

            # destination prefix <except> list
            if self.term.destination_prefix or self.term.destination_prefix_except:
                config.Append('destination-prefix-list {')
                for pfx in self.term.destination_prefix:
                    config.Append(pfx + ';')
                for epfx in self.term.destination_prefix_except:
                    config.Append(epfx + ' except;')
                config.Append('}')

            # protocol
            if self.term.protocol:
                # both are supported on JunOS, but only icmp6 is supported
                # on SRX loopback stateless filter
                config.Append(family_keywords['protocol'] + ' ' +
                              self._Group(self.term.protocol))

            # protocol
            if self.term.protocol_except:
                # same as above
                config.Append(family_keywords['protocol-except'] + ' ' +
                              self._Group(self.term.protocol_except))

            # port
            if self.term.port:
                config.Append('port %s' % self._Group(self.term.port))

            # source port
            if self.term.source_port:
                config.Append('source-port %s' %
                              self._Group(self.term.source_port))

            # destination port
            if self.term.destination_port:
                config.Append('destination-port %s' %
                              self._Group(self.term.destination_port))

            # append any options beloging in the from {} section
            for next_str in from_str:
                config.Append(next_str)

            # packet length
            if self.term.packet_length:
                config.Append('packet-length %s;' % self.term.packet_length)

            # fragment offset
            if self.term.fragment_offset:
                config.Append('fragment-offset %s;' %
                              self.term.fragment_offset)

            # icmp-types
            icmp_types = ['']
            if self.term.icmp_type:
                icmp_types = self.NormalizeIcmpTypes(self.term.icmp_type,
                                                     self.term.protocol,
                                                     self.term_type)
            if icmp_types != ['']:
                config.Append('icmp-type %s' % self._Group(icmp_types))

            if self.term.ether_type:
                config.Append('ether-type %s' %
                              self._Group(self.term.ether_type))

            if self.term.traffic_type:
                config.Append('traffic-type %s' %
                              self._Group(self.term.traffic_type))

            if self.term.precedence:
                # precedence may be a single integer, or a space separated list
                policy_precedences = set()
                # precedence values may only be 0 through 7
                for precedence in self.term.precedence:
                    if int(precedence) in range(0, 8):
                        policy_precedences.add(precedence)
                    else:
                        raise PrecedenceError(
                            'Precedence value %s is out of bounds in %s' %
                            (precedence, self.term.name))
                config.Append('precedence %s' %
                              self._Group(sorted(policy_precedences)))

            # DSCP Match
            if self.term.dscp_match:
                if self.term_type == 'inet6':
                    config.Append('traffic-class [ %s ];' %
                                  (' '.join(self.term.dscp_match)))
                else:
                    config.Append('dscp [ %s ];' %
                                  ' '.join(self.term.dscp_match))

            # DSCP Except
            if self.term.dscp_except:
                if self.term_type == 'inet6':
                    config.Append('traffic-class-except [ %s ];' %
                                  (' '.join(self.term.dscp_except)))
                else:
                    config.Append('dscp-except [ %s ];' %
                                  ' '.join(self.term.dscp_except))

            if self.term.hop_limit:
                # Only generate a hop-limit if inet6, inet4 has not hop-limit.
                if self.term_type == 'inet6':
                    config.Append('hop-limit %s;' % (self.term.hop_limit))

            # flexible-match
            if self.term.flexible_match_range:
                config.Append('flexible-match-range {')
                for fm_opt in self.term.flexible_match_range:
                    config.Append('%s %s;' % (fm_opt[0], fm_opt[1]))
                config.Append('}')

            config.Append('}')  # end from { ... }

        ####
        # ACTIONS go below here
        ####

        # If the action is only one line, include it in the same line as "then "
        # statement.
        # For example, if the action is only accept, it should be:
        # "then accept;" rather than:
        # "then {
        #     accept;
        # }"
        #
        unique_actions = set(self.extra_actions)
        if not self.term.routing_instance:
            unique_actions.update(self.term.action)
        if len(unique_actions) <= 1:
            for action in [
                    self.term.logging, self.term.routing_instance,
                    self.term.counter, self.term.policer, self.term.qos,
                    self.term.loss_priority, self.term.dscp_set,
                    self.term.next_ip, self.term.traffic_class_count
            ]:
                if action:
                    try:
                        unique_actions.update(action)
                    except TypeError:
                        unique_actions.add(action)
                    if len(unique_actions) > 1:
                        break

        if len(unique_actions) == 1:
            # b/21795531: Juniper device treats a set of IPv4 actions differently
            # than any other actions.
            # For example, if the term is in IPv4 and the action is only discard,
            # it should be:
            # "then {
            #     discard;
            # }" rather than:
            # "then discard;"
            current_action = self.ACTIONS.get(unique_actions.pop(), 'next_ip')
            if (self.term_type == 'inet' and current_action in [
                    'discard', 'reject', 'reject tcp-reset'
            ]) or (self.term_type == 'inet6'
                   and current_action in ['reject', 'reject tcp-reset']):
                config.Append('then {')
                config.Append('%s;' % current_action)
                config.Append('}')
            elif current_action == 'next_ip':
                self.NextIpCheck(self.term.next_ip, self.term.name)
                config.Append('then {')
                if self.term.next_ip[0].version == 4:
                    config.Append('next-ip %s;' % str(self.term.next_ip[0]))
                else:
                    config.Append('next-ip6 %s;' % str(self.term.next_ip[0]))
                config.Append('}')
            else:
                config.Append('then %s;' % current_action)
        elif len(unique_actions) > 1:
            config.Append('then {')
            # logging
            if self.term.logging:
                for log_target in self.term.logging:
                    if str(log_target) == 'local':
                        config.Append('log;')
                    else:
                        config.Append('syslog;')

            if self.term.routing_instance:
                config.Append('routing-instance %s;' %
                              self.term.routing_instance)

            if self.term.counter:
                config.Append('count %s;' % self.term.counter)

            if self.term.traffic_class_count:
                config.Append('traffic-class-count %s;' %
                              self.term.traffic_class_count)

            oid_length = 128
            if self.term.policer:
                config.Append('policer %s;' % self.term.policer)
                if len(self.term.policer) > oid_length:
                    logging.warn(
                        'WARNING: %s is longer than %d bytes. Due to limitation'
                        ' in JUNOS, OIDs longer than %dB can cause SNMP '
                        'timeout issues.', self.term.policer, oid_length,
                        oid_length)

            if self.term.qos:
                config.Append('forwarding-class %s;' % self.term.qos)

            if self.term.loss_priority:
                config.Append('loss-priority %s;' % self.term.loss_priority)
            if self.term.next_ip:
                self.NextIpCheck(self.term.next_ip, self.term.name)
                if self.term.next_ip[0].version == 4:
                    config.Append('next-ip %s;' % str(self.term.next_ip[0]))
                else:
                    config.Append('next-ip6 %s;' % str(self.term.next_ip[0]))
            for action in self.extra_actions:
                config.Append(action + ';')

            # If there is a routing-instance defined, skip reject/accept/etc actions.
            if not self.term.routing_instance:
                for action in self.term.action:
                    config.Append(self.ACTIONS.get(action) + ';')

            # DSCP SET
            if self.term.dscp_set:
                if self.term_type == 'inet6':
                    config.Append('traffic-class %s;' % self.term.dscp_set)
                else:
                    config.Append('dscp %s;' % self.term.dscp_set)

            config.Append('}')  # end then{...}

        config.Append('}')  # end term accept-foo-to-bar { ... }

        return str(config)
コード例 #7
0
    def __str__(self):
        # Verify platform specific terms. Skip whole term if platform does not
        # match.
        if self.term.platform:
            if self.platform not in self.term.platform:
                return ''
        if self.term.platform_exclude:
            if self.platform in self.term.platform_exclude:
                return ''

        ret_str = ['\n']

        # Don't render icmpv6 protocol terms under inet, or icmp under inet6
        if ((self.af == 6 and 'icmp' in self.term.protocol)
                or (self.af == 4 and 'icmpv6' in self.term.protocol)):
            logging.debug(
                self.NO_AF_LOG_PROTO.substitute(term=self.term.name,
                                                proto=self.term.protocol,
                                                af=self.text_af))
            return ''

        if self.term_remark:
            ret_str.append(' remark ' + self.term.name)
        if self.term.owner:
            self.term.comment.append('Owner: %s' % self.term.owner)
        for comment in self.term.comment:
            for line in comment.split('\n'):
                ret_str.append(' remark ' + str(line)[:100].rstrip())

        # Term verbatim output - this will skip over normal term creation
        # code by returning early.  Warnings provided in policy.py.
        if self.term.verbatim:
            for next_verbatim in self.term.verbatim:
                if next_verbatim.value[0] == self.platform:
                    ret_str.append(str(next_verbatim.value[1]))
                return '\n'.join(ret_str)

        # protocol
        if not self.term.protocol:
            if self.af == 6:
                protocol = ['ipv6']
            elif self.platform == 'ciscoxr':
                protocol = ['ipv4']
            else:
                protocol = ['ip']
        elif self.term.protocol == ['hopopt']:
            protocol = ['hbh']
        elif self.proto_int:
            protocol = [
                proto if proto in self.ALLOWED_PROTO_STRINGS else
                self.PROTO_MAP.get(proto) for proto in self.term.protocol
            ]
        else:
            protocol = self.term.protocol
        # source address
        if self.term.source_address:
            source_address = self.term.GetAddressOfVersion(
                'source_address', self.af)
            source_address_exclude = self.term.GetAddressOfVersion(
                'source_address_exclude', self.af)
            if source_address_exclude:
                source_address = nacaddr.ExcludeAddrs(source_address,
                                                      source_address_exclude)
            if not source_address:
                logging.debug(
                    self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                   direction='source',
                                                   af=self.text_af))
                return ''
            if self.enable_dsmo:
                source_address = summarizer.Summarize(source_address)
        else:
            # source address not set
            source_address = ['any']

        # destination address
        if self.term.destination_address:
            destination_address = self.term.GetAddressOfVersion(
                'destination_address', self.af)
            destination_address_exclude = self.term.GetAddressOfVersion(
                'destination_address_exclude', self.af)
            if destination_address_exclude:
                destination_address = nacaddr.ExcludeAddrs(
                    destination_address, destination_address_exclude)
            if not destination_address:
                logging.debug(
                    self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                   direction='destination',
                                                   af=self.text_af))
                return ''
            if self.enable_dsmo:
                destination_address = summarizer.Summarize(destination_address)
        else:
            # destination address not set
            destination_address = ['any']

        # options
        opts = [str(x) for x in self.term.option]
        if ((self.PROTO_MAP['tcp'] in protocol or 'tcp' in protocol)
                and ('tcp-established' in opts or 'established' in opts)):
            if 'established' not in self.options:
                self.options.append('established')

        # ports
        source_port = [()]
        destination_port = [()]
        if self.term.source_port:
            source_port = self._FixConsecutivePorts(self.term.source_port)

        if self.term.destination_port:
            destination_port = self._FixConsecutivePorts(
                self.term.destination_port)

        # logging
        if self.term.logging:
            self.options.append('log')

        # dscp; unlike srx, cisco only supports single, non-except values
        if self.term.dscp_match:
            if len(self.term.dscp_match) > 1:
                raise ExtendedAclTermError(
                    'Extended ACLs cannot specify more than one dscp match value'
                )
            else:
                self.options.append('dscp %s' % ' '.join(self.term.dscp_match))

        # icmp-types
        icmp_types = ['']
        if self.term.icmp_type:
            icmp_types = self.NormalizeIcmpTypes(self.term.icmp_type,
                                                 self.term.protocol, self.af)

        fixed_src_addresses = [self._GetIpString(x) for x in source_address]
        fixed_dst_addresses = [
            self._GetIpString(x) for x in destination_address
        ]
        fixed_src_ports = [self._FormatPort(x) for x in source_port]
        fixed_dst_ports = [self._FormatPort(x) for x in destination_port]
        fixed_opts = {}
        for p in protocol:
            fixed_opts[p] = self._FixOptions(p, self.options)
        for saddr in fixed_src_addresses:
            for daddr in fixed_dst_addresses:
                for sport in fixed_src_ports:
                    for dport in fixed_dst_ports:
                        for proto in protocol:
                            opts = fixed_opts[proto]
                            for icmp_type in icmp_types:
                                ret_str.extend(
                                    self._TermletToStr(
                                        _ACTION_TABLE.get(
                                            str(self.term.action[0])), proto,
                                        saddr, sport, daddr, dport, icmp_type,
                                        opts))

        return '\n'.join(ret_str)
コード例 #8
0
 def testSummarizeEmptyList(self):
     nets = []
     result = summarizer.Summarize(nets)
     self.assertEqual(result, [])