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 = []

    # Don't render icmpv6 protocol terms under inet, or icmp under inet6
    if ((self.af == 'inet6' and 'icmp' in self.term.protocol) or
        (self.af == '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.af))
      return ''

    # Term verbatim output - this will skip over most 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)

    # We don't support these keywords for filtering, so unless users
    # put in a "verbatim:: iptables" statement, any output we emitted
    # would misleadingly suggest that we applied their filters.
    # Instead, we fail loudly.
    if self.term.ether_type:
      raise UnsupportedFilterError('\n%s %s %s %s' % (
          'ether_type unsupported by', self._PLATFORM,
          '\nError in term', self.term.name))
    if self.term.address:
      raise UnsupportedFilterError('\n%s %s %s %s %s' % (
          'address unsupported by', self._PLATFORM,
          '- specify source or dest', '\nError in term:', self.term.name))
    if self.term.port:
      raise UnsupportedFilterError('\n%s %s %s %s %s' % (
          'port unsupported by', self._PLATFORM,
          '- specify source or dest', '\nError in term:', self.term.name))

    # Create a new term
    self._SetDefaultAction()
    if self._TERM_FORMAT:
      ret_str.append(self._TERM_FORMAT.substitute(term=self.term_name))

    if self._PREJUMP_FORMAT:
      ret_str.append(self._PREJUMP_FORMAT.substitute(filter=self.filter,
                                                     term=self.term_name))

    if self.term.owner:
      self.term.comment.append('Owner: %s' % self.term.owner)
    # reformat long comments, if needed
    #
    # iptables allows individual comments up to 256 chars.
    # But our generator will limit a single comment line to < 120, using:
    # max = 119 - 27 (static chars in comment command) - [length of term name]
    comment_max_width = 92 - len(self.term_name)
    if comment_max_width < 40:
      comment_max_width = 40
    comments = aclgenerator.WrapWords(self.term.comment, comment_max_width)
    # append comments to output
    if comments and comments[0]:
      for line in comments:
        if not line:
          continue  # iptables-restore does not like 0-length comments.
        # term comments
        ret_str.append(self._COMMENT_FORMAT.substitute(filter=self.filter,
                                                       term=self.term_name,
                                                       comment=str(line)))

    # Unsupported configuration; in the case of 'accept' or 'next', we
    # skip the rule.  In other cases, we blow up (raise an exception)
    # to ensure that this is not considered valid configuration.
    if self.term.source_prefix or self.term.destination_prefix:
      if str(self.term.action[0]) not in set(['accept', 'next']):
        raise UnsupportedFilterError('%s %s %s %s %s %s %s %s' % (
            '\nTerm', self.term.name, 'has action', str(self.term.action[0]),
            'with source_prefix or destination_prefix,',
            ' which is unsupported in', self._PLATFORM, 'iptables output.'))
      return ('# skipped %s due to source or destination prefix rule' %
              self.term.name)

    # protocol
    if self.term.protocol:
      protocol = self.term.protocol
    else:
      protocol = ['all']
    if self.term.protocol_except:
      raise UnsupportedFilterError('%s %s %s' % (
          '\n', self.term.name,
          'protocol_except logic not currently supported.'))

    (term_saddr, exclude_saddr,
     term_daddr, exclude_daddr) = self._CalculateAddresses(
         self.term.source_address, self.term.source_address_exclude,
         self.term.destination_address, self.term.destination_address_exclude)
    if not term_saddr:
      logging.debug(self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                   direction='source',
                                                   af=self.af))
      return ''
    if not term_daddr:
      logging.debug(self.NO_AF_LOG_ADDR.substitute(term=self.term.name,
                                                   direction='destination',
                                                   af=self.af))
      return ''

    # 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

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

    source_interface = ''
    if self.term.source_interface:
      source_interface = self.term.source_interface

    destination_interface = ''
    if self.term.destination_interface:
      destination_interface = self.term.destination_interface

    log_hits = False
    if self.term.logging:
      # Iptables sends logs to hosts configured syslog
      log_hits = True

    # options
    tcp_flags = []
    tcp_track_options = []
    for next_opt in [str(x) for x in self.term.option]:
      #
      # Sanity checking and high-ports are added as appropriate in
      # pre-processing that is done in __str__ within class Iptables.
      # Option established will add destination port high-ports if protocol
      # contains only tcp, udp or both.  This is done earlier in class Iptables.
      #
      if ((next_opt.find('established') == 0 or
           next_opt.find('tcp-established') == 0)
          and 'ESTABLISHED' not in [x.strip() for x in self.options]):
        if next_opt.find('tcp-established') == 0 and protocol != ['tcp']:
          raise TcpEstablishedError('%s %s %s' % (
              '\noption tcp-established can only be applied for proto tcp.',
              '\nError in term:', self.term.name))

        if self.trackstate:
          # Use nf_conntrack to track state -- works with any proto
          self.options.append('-m state --state ESTABLISHED,RELATED')
        elif protocol == ['tcp']:
          # Simple established-only rule for TCP: Must have ACK field
          # (SYN/ACK or subsequent ACK), or RST and no other flags.
          tcp_track_options = [(['ACK'], ['ACK']),
                               (['SYN', 'FIN', 'ACK', 'RST'], ['RST'])]

      # Iterate through flags table, and create list of tcp-flags to append
      for next_flag in self._TCP_FLAGS_TABLE:
        if next_opt.find(next_flag) == 0:
          tcp_flags.append(self._TCP_FLAGS_TABLE.get(next_flag))
      if next_opt in self._KNOWN_OPTIONS_MATCHERS:
        self.options.append(self._KNOWN_OPTIONS_MATCHERS[next_opt])
    if self.term.packet_length:
      # Policy format is "#-#", but iptables format is "#:#"
      self.options.append('-m length --length %s' %
                          self.term.packet_length.replace('-', ':'))
    if self.term.fragment_offset:
      self.options.append('-m u32 --u32 4&0x1FFF=%s' %
                          self.term.fragment_offset.replace('-', ':'))

    for saddr in exclude_saddr:
      ret_str.extend(self._FormatPart(
          '', saddr, '', '', '', '', '', '', '', '', '', '',
          self._ACTION_TABLE.get('next')))
    for daddr in exclude_daddr:
      ret_str.extend(self._FormatPart(
          '', '', '', daddr, '', '', '', '', '', '', '', '',
          self._ACTION_TABLE.get('next')))

    for saddr in term_saddr:
      for daddr in term_daddr:
        for icmp in icmp_types:
          for proto in protocol:
            for tcp_matcher in tcp_track_options or (([], []),):
              ret_str.extend(self._FormatPart(
                  str(proto),
                  saddr,
                  source_port,
                  daddr,
                  destination_port,
                  self.options,
                  tcp_flags,
                  icmp,
                  tcp_matcher,
                  source_interface,
                  destination_interface,
                  log_hits,
                  self._ACTION_TABLE.get(str(self.term.action[0]))
                  ))

    if self._POSTJUMP_FORMAT:
      ret_str.append(self._POSTJUMP_FORMAT.substitute(filter=self.filter,
                                                      term=self.term_name))

    return '\n'.join(str(v) for v in ret_str if v is not '')
dataset/ETHPy150Open google/capirca/lib/iptables.py/Term.__str__/original