def rule(cmd, p, &block)
      # Evaluate a block expression and return early if it evaluates to false.
      # If no block is passed it is equivalent to the block: { true }.
      return self if block_given? && !instance_eval(&block)

      raise ArgumentError, 'chain is a required argument' unless p[:chain]
      assert_valid_ipaddr(p[:src]) if p[:src]
      assert_valid_ipaddr(p[:dst]) if p[:dst]

      # Map of commands for rules
      cmds = {
        add: '-A', delete: '-D', insert: '-I', replace: '-R', check: '-C'
      }

      @buffer << [
        'iptables', option('-t', @table), cmds[cmd], p[:chain],
        option(false, p[:rulenum]), option('-f', p[:frag]),
        option('-s', p[:src]), option('-d', p[:dst]),
        option('-o', p[:out]), option('-i', p[:in]),
        option('-p', p[:proto] || 'tcp'), option('-m', p[:match] || @match),
        option('--sport', p[:sports] || @sports),
        option('--dport', p[:dports] || @dports), p[:jump] || p[:goto],
        option('--to-port', p[:to_port])
      ].compact.join(' ') << "\n"

      self
    end
def rule(cmd, p, &block)
      # Evaluate a block expression and return early if it evaluates to false.
      # If no block is passed it is equivalent to the block: { true }.
      return self if block_given? && !instance_eval(&block)

      raise ArgumentError, 'chain is a required argument' unless p[:chain]
      assert_valid_ipaddr(p[:src]) if p[:src]
      assert_valid_ipaddr(p[:dst]) if p[:dst]

      # Map of commands for rules
      cmds = {
        add: '-A', delete: '-D', insert: '-I', replace: '-R', check: '-C'
      }

      @buffer << [
        'iptables', option('-t', @table), cmds[cmd], p[:chain],
        option(false, p[:rulenum]), option('-f', p[:frag]),
        option('-s', p[:src]), option('-d', p[:dst]),
        option('-o', p[:out]), option('-i', p[:in]),
        option('-p', p[:proto] || 'tcp'), option('-m', p[:match] || @match),
        option('--sport', p[:sports] || @sports),
        option('--dport', p[:dports] || @dports), p[:jump] || p[:goto],
        option('--to-port', p[:to_port])
      ].compact.join(' ') << "\n"

      self
    end
Create, flush and delete chains
 @param [String] cmd the operation to perform (add, delete, insert, etc.)
 @param [Hash] p parameters for specific iptables features.
 @param [Block] block will evaluate a block that will return true/false.
 @return self