def _CalculateAddrList(self, addr_list, addr_exclude_list, target_af, direction): """Calculates and stores address list for target AF and direction. Args: addr_list: address list. addr_exclude_list: address exclude list of the term. target_af: target address family. direction: direction in which address list will be used. Returns: calculated address list. """ if not addr_list: addr_list = [self._all_ips] addr_list = [addr for addr in addr_list if addr.version == target_af] if addr_exclude_list: addr_exclude_list = [ addr_exclude for addr_exclude in addr_exclude_list if addr_exclude.version == target_af ] addr_list = nacaddr.ExcludeAddrs(addr_list, addr_exclude_list) if len(addr_list) > 1: set_name = self._GenerateSetName(self.term.name, direction) self.addr_sets[direction] = (set_name, addr_list) addr_list = [self._all_ips] return addr_list
def _CalculateAddrs(self, addr_list, addr_exclude_list): addr_list = [addr for addr in addr_list if addr.version == self.AF_MAP[self.af]] if addr_exclude_list: if not addr_list: addr_list = [self.all_ips] addr_list = nacaddr.ExcludeAddrs(addr_list, addr_exclude_list) return addr_list
def _CalculateAddresses(self, term_saddr, exclude_saddr, term_daddr, exclude_daddr): """Calculate source and destination address list for a term. Args: term_saddr: source address list of the term exclude_saddr: source address exclude list of the term term_daddr: destination address list of the term exclude_daddr: destination address exclude list of the term Returns: tuple containing source address list, source exclude address list, destination address list, destination exclude address list in that order """ # source address term_saddr_excluded = [] if not term_saddr: term_saddr = [self._all_ips] if exclude_saddr: term_saddr_excluded.extend( nacaddr.ExcludeAddrs(term_saddr, exclude_saddr)) # destination address term_daddr_excluded = [] if not term_daddr: term_daddr = [self._all_ips] if exclude_daddr: term_daddr_excluded.extend( nacaddr.ExcludeAddrs(term_daddr, exclude_daddr)) # Just to be safe, always have a result of at least 1 to avoid * by zero # returning incorrect results (10src*10dst=100, but 10src*0dst=0, not 10) bailout_count = len(exclude_saddr) + len(exclude_daddr) + ( (len(self.term.source_address) or 1) * (len(self.term.destination_address) or 1)) exclude_count = ((len(term_saddr_excluded) or 1) * (len(term_daddr_excluded) or 1)) # Use bailout jumps for excluded addresses if it results in fewer output # lines than nacaddr.ExcludeAddrs() method. if exclude_count < bailout_count: exclude_saddr = [] exclude_daddr = [] if term_saddr_excluded: term_saddr = term_saddr_excluded if term_daddr_excluded: term_daddr = term_daddr_excluded # With many sources and destinations, iptables needs to generate the # cartesian product of sources and destinations. If there are no # exclude rules, this can instead be written as exclude [0/0 - # srcs], exclude [0/0 - dsts]. v4_src_count = len([x for x in term_saddr if x.version == 4]) v4_dst_count = len([x for x in term_daddr if x.version == 4]) v6_src_count = len([x for x in term_saddr if x.version == 6]) v6_dst_count = len([x for x in term_daddr if x.version == 6]) num_pairs = v4_src_count * v4_dst_count + v6_src_count * v6_dst_count if num_pairs > 100: new_exclude_source = nacaddr.ExcludeAddrs([self._all_ips], term_saddr) new_exclude_dest = nacaddr.ExcludeAddrs([self._all_ips], term_daddr) # Invert the shortest list that does not already have exclude addresses if len(new_exclude_source) < len( new_exclude_dest) and not exclude_saddr: if len(new_exclude_source) + len(term_daddr) < num_pairs: exclude_saddr = new_exclude_source term_saddr = [self._all_ips] elif not exclude_daddr: if len(new_exclude_dest) + len(term_saddr) < num_pairs: exclude_daddr = new_exclude_dest term_daddr = [self._all_ips] term_saddr = [ x for x in term_saddr if x.version == self.AF_MAP[self.af] ] exclude_saddr = [ x for x in exclude_saddr if x.version == self.AF_MAP[self.af] ] term_daddr = [ x for x in term_daddr if x.version == self.AF_MAP[self.af] ] exclude_daddr = [ x for x in exclude_daddr if x.version == self.AF_MAP[self.af] ] return (term_saddr, exclude_saddr, term_daddr, exclude_daddr)
def __str__(self): """Convert term to a rule string. Returns: A rule as a string. Raises: NsxvAclTermError: When unknown icmp-types are specified """ # Verify platform specific terms. Skip whole term if platform does not # match. if self.term.platform: if 'nsxv' not in self.term.platform: return '' if self.term.platform_exclude: if 'nsxv' in self.term.platform_exclude: return '' ret_str = [''] # 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.filter_type)) return '' # Term verbatim is not supported if self.term.verbatim: raise NsxvAclTermError( 'Verbatim are not implemented in standard ACLs') # Term option is not supported if self.term.option: for opt in [ str(single_option) for single_option in self.term.option ]: if ((opt.find('tcp-established') == 0) or (opt.find('established') == 0)): return '' else: raise NsxvAclTermError( 'Option are not implemented in standard ACLs') # check for keywords Nsxv does not support term_keywords = self.term.__dict__ unsupported_keywords = [] for key in term_keywords: if term_keywords[key]: # translated is obj attribute not keyword if ('translated' not in key) and (key not in _NSXV_SUPPORTED_KEYWORDS): unsupported_keywords.append(key) if unsupported_keywords: logging.warning( 'WARNING: The keywords %s in Term %s are not supported ' 'in Nsxv ', unsupported_keywords, self.term.name) name = '%s%s%s' % (_XML_TABLE.get('nameStart'), self.term.name, _XML_TABLE.get('nameEnd')) notes = '' if self.term.comment: for comment in self.term.comment: notes = '%s%s' % (notes, comment) notes = '%s%s%s' % (_XML_TABLE.get('noteStart'), notes, _XML_TABLE.get('noteEnd')) # protocol protocol = None if self.term.protocol: protocol = list( map(self.PROTO_MAP.get, self.term.protocol, self.term.protocol)) # icmp-types icmp_types = [''] if self.term.icmp_type: icmp_types = self.NormalizeIcmpTypes(self.term.icmp_type, self.term.protocol, self.af) # for mixed filter type get both IPV4address and IPv6Address af_list = [] if self.filter_type == 'mixed': af_list = [4, 6] else: af_list = [self.af] source_address = None destination_address = None source_addr = [] destination_addr = [] source_v4_addr = [] source_v6_addr = [] dest_v4_addr = [] dest_v6_addr = [] for af in af_list: # source address if self.term.source_address: source_address = self.term.GetAddressOfVersion( 'source_address', af) source_address_exclude = self.term.GetAddressOfVersion( 'source_address_exclude', af) if source_address_exclude: source_address = nacaddr.ExcludeAddrs( source_address, source_address_exclude) if source_address: if af == 4: source_v4_addr = source_address else: source_v6_addr = source_address source_addr = source_v4_addr + source_v6_addr # destination address if self.term.destination_address: destination_address = self.term.GetAddressOfVersion( 'destination_address', af) destination_address_exclude = self.term.GetAddressOfVersion( 'destination_address_exclude', af) if destination_address_exclude: destination_address = nacaddr.ExcludeAddrs( destination_address, destination_address_exclude) if destination_address: if af == 4: dest_v4_addr = destination_address else: dest_v6_addr = destination_address destination_addr = dest_v4_addr + dest_v6_addr # Check for mismatch IP for source and destination address for mixed filter if self.filter_type == 'mixed': if source_addr and destination_addr: if source_v4_addr and not dest_v4_addr: source_addr = source_v6_addr elif source_v6_addr and not dest_v6_addr: source_addr = source_v4_addr elif dest_v4_addr and not source_v4_addr: destination_addr = dest_v6_addr elif dest_v6_addr and not source_v6_addr: destination_addr = dest_v4_addr if not source_addr or not destination_addr: logging.warning( 'Term %s will not be rendered as it has IPv4/IPv6 ' 'mismatch for source/destination for mixed address ' 'family.', self.term.name) return '' # ports source_port = None destination_port = None if self.term.source_port: source_port = self.term.source_port if self.term.destination_port: destination_port = self.term.destination_port # logging log = 'false' if self.term.logging: log = 'true' sources = '' if source_addr: sources = '<sources excluded="false">' for saddr in source_addr: # inet4 if isinstance(saddr, nacaddr.IPv4): if saddr.num_addresses > 1: saddr = '%s%s%s' % ( _XML_TABLE.get('srcIpv4Start'), saddr.with_prefixlen, _XML_TABLE.get('srcIpv4End'), ) else: saddr = '%s%s%s' % (_XML_TABLE.get('srcIpv4Start'), saddr.network_address, _XML_TABLE.get('srcIpv4End')) sources = '%s%s' % (sources, saddr) # inet6 if isinstance(saddr, nacaddr.IPv6): if saddr.num_addresses > 1: saddr = '%s%s%s' % ( _XML_TABLE.get('srcIpv6Start'), saddr.with_prefixlen, _XML_TABLE.get('srcIpv6End'), ) else: saddr = '%s%s%s' % (_XML_TABLE.get('srcIpv6Start'), saddr.network_address, _XML_TABLE.get('srcIpv6End')) sources = '%s%s' % (sources, saddr) sources = '%s%s' % (sources, '</sources>') destinations = '' if destination_addr: destinations = '<destinations excluded="false">' for daddr in destination_addr: # inet4 if isinstance(daddr, nacaddr.IPv4): if daddr.num_addresses > 1: daddr = '%s%s%s' % ( _XML_TABLE.get('destIpv4Start'), daddr.with_prefixlen, _XML_TABLE.get('destIpv4End'), ) else: daddr = '%s%s%s' % (_XML_TABLE.get('destIpv4Start'), daddr.network_address, _XML_TABLE.get('destIpv4End')) destinations = '%s%s' % (destinations, daddr) # inet6 if isinstance(daddr, nacaddr.IPv6): if daddr.num_addresses > 1: daddr = '%s%s%s' % ( _XML_TABLE.get('destIpv6Start'), daddr.with_prefixlen, _XML_TABLE.get('destIpv6End'), ) else: daddr = '%s%s%s' % (_XML_TABLE.get('destIpv6Start'), daddr.network_address, _XML_TABLE.get('destIpv6End')) destinations = '%s%s' % (destinations, daddr) destinations = '%s%s' % (destinations, '</destinations>') services = [] if protocol: services.append('<services>') for proto in protocol: if proto != 'any': services.append( self._ServiceToString(proto, source_port, destination_port, icmp_types)) services.append('</services>') service = '' for s in services: service = '%s%s' % (service, s) # applied_to applied_to_list = '' if self.applied_to: applied_to_list = '<appliedToList>' applied_to_element = '%s%s%s' % (_XML_TABLE.get('appliedToStart'), self.applied_to, _XML_TABLE.get('appliedToEnd')) applied_to_list = '%s%s' % (applied_to_list, applied_to_element) applied_to_list = '%s%s' % (applied_to_list, '</appliedToList>') # action action = '%s%s%s' % (_XML_TABLE.get('actionStart'), _ACTION_TABLE.get(str(self.term.action[0])), _XML_TABLE.get('actionEnd')) ret_lines = [] ret_lines.append('<rule logged="%s">%s%s%s%s%s%s%s</rule>' % (log, name, action, sources, destinations, service, applied_to_list, notes)) # remove any trailing spaces and replace multiple spaces with singles stripped_ret_lines = [ re.sub(r'\s+', ' ', x).rstrip() for x in ret_lines ] ret_str.extend(stripped_ret_lines) return ''.join(ret_str)
def __str__(self): # Verify platform specific terms. Skip whole term if platform does not # match. if self.term.platform: if 'ciscoasa' not in self.term.platform: return '' if self.term.platform_exclude: if 'ciscoasa' 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)): ret_str.append('remark Term %s' % self.term.name) ret_str.append('remark not rendered due to protocol/AF mismatch.') return '\n'.join(ret_str) ret_str.append('access-list %s remark %s' % (self.filter_name, 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('access-list %s remark %s' % (self.filter_name, str(line)[:100])) # Term verbatim output - this will skip over normal term creation # code by returning early. Warnings provided in policy.py. if self.term.verbatim: for line in self.term.verbatim: if line[0] == 'ciscoasa': ret_str.append(str(line[1])) return '\n'.join(ret_str) # protocol if not self.term.protocol: protocol = ['ip'] else: # fix the protocol 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) 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) else: # destination address not set destination_address = ['any'] # options extra_options = [] for opt in [str(x) for x in self.term.option]: if opt.find('tcp-established') == 0 and 6 in protocol: extra_options.append('established') elif opt.find('established') == 0 and 6 in protocol: # only needed for TCP, for other protocols policy.py handles high-ports extra_options.append('established') self.options.extend(extra_options) # ports source_port = [()] destination_port = [()] if self.term.source_port: source_port = self.term.source_port if self.term.destination_port: destination_port = self.term.destination_port # logging if self.term.logging: self.options.append('log') if 'disable' in [x.value for x in self.term.logging]: self.options.append('disable') # icmp-types icmp_types = [''] if self.term.icmp_type: icmp_types = self.NormalizeIcmpTypes(self.term.icmp_type, self.term.protocol, self.af) for saddr in source_address: for daddr in destination_address: for sport in source_port: for dport in destination_port: for proto in protocol: for icmp_type in icmp_types: # only output address family appropriate IP addresses do_output = False if self.af == 4: if (((isinstance(saddr, nacaddr.IPv4)) or (saddr == 'any')) and ((isinstance(daddr, nacaddr.IPv4)) or (daddr == 'any'))): do_output = True if self.af == 6: if (((isinstance(saddr, nacaddr.IPv6)) or (saddr == 'any')) and ((isinstance(daddr, nacaddr.IPv6)) or (daddr == 'any'))): do_output = True if do_output: ret_str.extend( self._TermletToStr( self.filter_name, _ACTION_TABLE.get( str(self.term.action[0])), proto, saddr, sport, daddr, dport, icmp_type, self.options)) return '\n'.join(ret_str)
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=', '.join( self.term.protocol), af=self.text_af)) return '' if self.verbose: 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[0] == self.platform: ret_str.append(str(next_verbatim[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 # Arista can not process acls with esp/ah, these must appear as integers. if self.platform == 'arista': if 'esp' in protocol: protocol = [x if x != 'esp' else '50' for x in protocol] if 'ah' in protocol: protocol = [x if x != 'ah' else '51' for x in 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') # Using both 'fragments' and 'is-fragment', ref Github Issue #187 if ('ip' in protocol) and (('fragments' in opts) or ('is-fragment' in opts)): if 'fragments' not in self.options: self.options.append('fragments') # ACL-based Forwarding if (self.platform == 'ciscoxr' ) and not self.term.action and self.term.next_ip and ('nexthop1' not in opts): if len(self.term.next_ip) > 1: raise CiscoNextIpError( 'The following term has more than one next IP ' 'value: %s' % self.term.name) if (not isinstance(self.term.next_ip[0], nacaddr.IPv4) and not isinstance(self.term.next_ip[0], nacaddr.IPv6)): raise CiscoNextIpError('Next IP value must be an IP address. ' 'Invalid term: %s' % self.term.name) if self.term.next_ip[0].num_addresses > 1: raise CiscoNextIpError( 'The following term has a subnet instead of a ' 'host: %s' % self.term.name) nexthop = self.term.next_ip[0].network_address nexthop_protocol = 'ipv4' if nexthop.version == 4 else 'ipv6' self.options.append('nexthop1 %s %s' % (nexthop_protocol, nexthop)) action = _ACTION_TABLE.get('accept') if self.term.action: action = _ACTION_TABLE.get(str(self.term.action[0])) # 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) icmp_codes = [''] if self.term.icmp_code: icmp_codes = self.term.icmp_code fixed_src_addresses = [self._GetIpString(x) for x in source_address] fixed_dst_addresses = [ self._GetIpString(x) for x in destination_address ] 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 source_port: for dport in destination_port: for proto in protocol: opts = fixed_opts[proto] for icmp_type in icmp_types: for icmp_code in icmp_codes: ret_str.extend( self._TermletToStr( action, proto, saddr, self._FormatPort(sport, proto), daddr, self._FormatPort(dport, proto), icmp_type, icmp_code, opts)) return '\n'.join(ret_str)
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) icmp_codes = [''] if self.term.icmp_code: icmp_codes = self.term.icmp_code fixed_src_addresses = [self._GetIpString(x) for x in source_address] fixed_dst_addresses = [ self._GetIpString(x) for x in destination_address ] 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 source_port: for dport in destination_port: for proto in protocol: opts = fixed_opts[proto] for icmp_type in icmp_types: for icmp_code in icmp_codes: ret_str.extend( self._TermletToStr( _ACTION_TABLE.get( str(self.term.action[0])), proto, saddr, self._FormatPort(sport, proto), daddr, self._FormatPort(dport, proto), icmp_type, icmp_code, opts)) return '\n'.join(ret_str)