function cmd::fw::list() {
  local peer="" type=""
  local show_nflog=true show_accept=true show_drop=true

  while [[ $# -gt 0 ]]; do
    case "$1" in
      --peer)         peer="$2";          shift 2 ;;
      --type)         type="$2";          shift 2 ;;
      --no-nflog)     show_nflog=false;   shift   ;;
      --no-accept)    show_accept=false;  shift   ;;
      --no-drop)      show_drop=false;    shift   ;;
      *) shift ;;
    esac
  done

  log::section "Firewall Rules (FORWARD)"
  printf "\n"

  if [[ -n "$peer" ]]; then
    local ip
    ip=$(peers::get_ip "$peer")
    [[ -z "$ip" ]] && log::error "Peer not found: $peer" && return 1
    iptables -L FORWARD -n -v | grep -F "$ip" | while IFS= read -r rule; do
      [[ -z "$rule" ]] && continue
      ! $show_nflog  && [[ "$rule" =~ NFLOG ]] && continue
      ! $show_accept && [[ "$rule" =~ ACCEPT ]] && continue
      ! $show_drop   && [[ "$rule" =~ DROP ]] && continue
      ui::firewall_rule "$rule"
    done
  elif [[ -n "$type" ]]; then
    local subnet
    subnet=$(config::subnet_for "$type")
    [[ -z "$subnet" ]] && log::error "Unknown type: $type" && return 1
    iptables -L FORWARD -n -v | grep -F "$subnet" | while IFS= read -r rule; do
      [[ -z "$rule" ]] && continue
      ! $show_nflog  && [[ "$rule" =~ NFLOG ]] && continue
      ! $show_accept && [[ "$rule" =~ ACCEPT ]] && continue
      ! $show_drop   && [[ "$rule" =~ DROP ]] && continue
      ui::firewall_rule "$rule"
    done
  else
    iptables -L FORWARD -n -v \
      | grep -v "^Chain\|^target\|^$\|ACCEPT.*0\.0\.0\.0.*0\.0\.0\.0" \
      | while IFS= read -r rule; do
        [[ -z "$rule" ]] && continue
        ! $show_nflog  && [[ "$rule" =~ NFLOG ]] && continue
        ! $show_accept && [[ "$rule" =~ ACCEPT ]] && continue
        ! $show_drop   && [[ "$rule" =~ DROP ]] && continue
        ui::firewall_rule "$rule"
      done
  fi

  printf "\n"
}