def _FormatPart(self, protocol, saddr, sport, daddr, dport, options,
                  tcp_flags, icmp_type, track_flags, sint, dint, log_hits,
                  action):
    """Compose one iteration of the term parts into a string.

    Args:
      protocol: The network protocol
      saddr: Source IP address
      sport: Source port numbers
      daddr: Destination IP address
      dport: Destination port numbers
      options: Optional arguments to append to our rule
      tcp_flags: Which tcp_flag arguments, if any, should be appended
      icmp_type: What icmp protocol to allow, if any
      track_flags: A tuple of ([check-flags], [set-flags]) arguments to tcp-flag
      sint: Optional source interface
      dint: Optional destination interface
      log_hits: Boolean, to log matches or not
      action: What should happen if this rule matches
    Returns:
      rval:  A single iptables argument line
    """
    src, dst = self._GenerateAddressStatement(saddr, daddr)

    filter_top = self._FILTER_TOP_FORMAT.substitute(filter=self.filter,
                                                    term=self.term_name)

    source_int = ''
    if sint:
      source_int = '-i %s' % sint

    destination_int = ''
    if dint:
      destination_int = '-o %s' % dint

    log_jump = ''
    if log_hits:
      log_jump = self._LOG_FORMAT.substitute(term=self.term.name)

    if not options:
      options = []

    proto = self._PROTO_TABLE.get(str(protocol))
    # Don't drop protocol if we don't recognize it
    if protocol and not proto:
      proto = '-p %s' % str(protocol)

    # TODO(vklimovs): generalize to all v6 special cases
    # Use u32 module as named modules are not available
    # everywhere.
    if protocol == 'hop-by-hop':
      proto = ''
      # Select 4 bytes at offset 0x3, mask out all but
      # last byte. That produces byte at position 7,
      # Next Header. Compare to 0x0, Hop By Hop
      options.append('-m u32 --u32 "0x3&0xff=0x0"')
    if protocol == 'fragment':
      proto = ''
      # Ditto, but compare to 0x2c, 44, Fragment
      options.append('-m u32 --u32 "0x3&0xff=0x2c"')

    # set conntrack state to NEW, unless policy requested "nostate"
    if self.trackstate:
      already_stateful = False
      # we will add new stateful arguments only if none already exist, such
      # as from "option:: established"
      for option in options:
        if 'state' in option:
          already_stateful = True
      if not already_stateful:
        if 'ACCEPT' in action:
          # We have to permit established/related since a policy may not
          # have an existing blank permit for established/related, which
          # may be more efficient, but slightly less secure.
          options.append('-m state --state NEW,ESTABLISHED,RELATED')

    if tcp_flags or (track_flags and track_flags[0]):
      check_fields = ','.join(sorted(set(tcp_flags + track_flags[0])))
      set_fields = ','.join(sorted(set(tcp_flags + track_flags[1])))
      flags = (check_fields, set_fields) % '--tcp-flags %s %s'
    else:
      flags = ''

    icmp_type = str(icmp_type)
    if not icmp_type:
      icmp = ''
    elif str(protocol) == 'icmpv6':
      icmp = '-m icmp6 --icmpv6-type %s' % icmp_type
    else:
      icmp = '--icmp-type %s' % icmp_type

    # format tcp and udp ports
    sports = dports = ['']
    if sport:
      sports = self._GeneratePortStatement(sport, source=True)
    if dport:
      dports = self._GeneratePortStatement(dport, dest=True)

    ret_lines = []
    for sport in sports:
      for dport in dports:
        rval = [filter_top]
        if re.search('multiport', sport) and not re.search('multiport', dport):
          # Due to bug in iptables, use of multiport module before a single
          # port specification will result in multiport trying to consume it.
          # this is a little hack to ensure single ports are listed before
          # any multiport specification.
          dport, sport = sport, dport
        if str(protocol) == 'icmpv6':
          # Due to a bug in ip6tables, iptables-save returns icmpv6 matches in
          # order (address spec) (icmpv6 spec). Fake this using options
          # datastructure.
          options.extend((proto, icmp))
          proto = ''
          icmp = ''
        if (str(self.af) == 'inet6' and
            str(protocol) == 'all' and
            'REJECT' in str(action)):
          # Due to a bug in ip6tables, when -p all and -j REJECT, proto
          # is being eaten
          proto = ''
        for value in (proto, flags, sport, dport, icmp, src, dst,
                      ' '.join(options), source_int, destination_int):
          if value:
            rval.append(str(value))
        if log_jump:
          # -j LOG
          ret_lines.append(' '.join(rval+[log_jump]))
        # -j ACTION
        ret_lines.append(' '.join(rval+[action]))
    return ret_lines
dataset/ETHPy150Open google/capirca/lib/iptables.py/Term._FormatPart/swapped operands of `%`