#!/system/bin/sh
#
# simple script to turn monitor mode for the WLAN interface on or off
#
#h#
#h# Usage: configure_wlan_monitor_mode.sh [on|off|enable|disable|status] [if=interface] [executable_to_execute] [parameter_for_the executable]
#h# 
#h# The default interface is wlan0
#h# 
#
# Returncode:
#   if the parameter status is used the script returns 0 if the monitor mode is enabled and 1 if not
#   if the parameter for an executable to execute is used the script returns the returncode of that executable
#
# History
#  23.08.2024 v1.0.0 /bs
#   initial version
#
# Credits:
#   https://github.com/kimocoder/qualcomm_android_monitor_mode
#

__TRUE=0
__FALSE=1

DEFAULT_WLAN_INTERFACE="wlan0"
WLAN_INTERFACE="${DEFAULT_WLAN_INTERFACE}"

CUR_COMMAND=""
CUR_COMMAND_PARAMETER=""

CUR_USER="$( id -un )"
if [ "${CUR_USER}"x != "root"x ] ; then
  PREFIX="su - -c "
else
  PREFIX=""
fi

if [[ $0 == *enable_monitor_mode ]] ; then
  set -- on
elif [[ $0 == *disable_monitor_mode ]] ; then
  set -- off
elif [[ $0 == *monitor_mode_status || $0 == *read_monitor_mode ]] ; then
  set -- status
fi

# ----------------------------------------------------------------------
# LogMsg
#
# function: write a message to STDOUT
#
# usage: LogMsg [message]
#
function LogMsg {
  typeset THISMSG="$*"

  echo "${THISMSG}"
}


# ----------------------------------------------------------------------
# LogError
#
# function: write a message prefixed with "ERROR:" to STDERR
#
# usage: LogError [message]
#
function LogError {
  typeset THISMSG="$*"

  LogMsg "ERROR: ${THISMSG}" >&2
}


# ----------------------------------------------------------------------
# die
#
# function: print a message and end the script
#
# usage: die [script_exit_code] [message]
#
# the parameter "message" is optional; the script will add a leading "ERROR: "
# to the message if the script_exit_code is not zero
#
# returns: n/a
#
function die  {
  typeset THISRC=$1
  [ $# -ne 0 ] && shift
  typeset THISMSG="$*"

  if [ "${THISMSG}"x != ""x ] ; then
    if [ ${THISRC} != 0 ] ; then
      LogError "${THISMSG} (RC=${THISRC})" >&2
    else
      LogMsg "${THISMSG}"
    fi
  fi

  exit ${THISRC}
}
# Start monitor mode on adapter


# ----------------------------------------------------------------------
# enable_monitor_mode
#
# function: enable the monitor mode
#
# usage: enable_monitor_mode [interface]
#
#
function enable_monitor_mode {
  typeset CUR_WLAN_INTERFACE="${WLAN_INTERFACE}"
  [ $# -eq 1 ] && CUR_WLAN_INTERFACE="$1"
  
  ${PREFIX} ip link set ${CUR_WLAN_INTERFACE} down
  if [ "${PREFIX}"x != ""x ] ; then
    ${PREFIX} "echo 4 >/sys/module/wlan/parameters/con_mode "
  else
     echo 4 >/sys/module/wlan/parameters/con_mode 
  fi
  
  ${PREFIX} ip link set ${CUR_WLAN_INTERFACE} up
}

# Stop monitor mode on adapter


# ----------------------------------------------------------------------
# disable_monitor_mode
#
# function: disable the monitor mode
#
# usage: disable_monitor_mode [interface]
#
#
function disable_monitor_mode {
  typeset CUR_WLAN_INTERFACE="${WLAN_INTERFACE}"
  [ $# -eq 1 ] && CUR_WLAN_INTERFACE="$1"
  
  ${PREFIX} ip link set wlan0 down

  if [ "${PREFIX}"x != ""x ] ; then
    ${PREFIX} "echo 0 >/sys/module/wlan/parameters/con_mode "
  else
     echo 0 >/sys/module/wlan/parameters/con_mode 
  fi

  ${PREFIX} ip link set ${CUR_WLAN_INTERFACE} up
}

# ----------------------------------------------------------------------
# read_monitor_mode
#
# function: read the monitor mode
#
# usage: read_monitor_mode [interface]
#
# returns:
#   0 - the monitor mode is enabled
#   1 - the monitor mode is disabled
#  99 - the status of the monitor mode is unknown
#  98 - unknown error
#
function read_monitor_mode {
  typeset THISRC=98

  typeset CUR_WLAN_INTERFACE="${WLAN_INTERFACE}"
  [ $# -eq 1 ] && CUR_WLAN_INTERFACE="$1"
  
  
  CUR_MONITOR_MODE=$( ${PREFIX} cat /sys/module/wlan/parameters/con_mode )
  case ${CUR_MONITOR_MODE} in
    0 ) 
      LogMsg "The monitor  mode for the interface \"${CUR_WLAN_INTERFACE}\" is disabled"
      THISRC=${__FALSE}
      ;;

    4 ) 
      LogMsg "The monitor  mode for the interface \"${CUR_WLAN_INTERFACE}\" is enabled"
      THISRC=${__TRUE}
      ;;

    * ) 
      LogMsg "The monitor  mode for the interface \"${CUR_WLAN_INTERFACE}\" is unknown: ${CUR_MONITOR_MODE}"
      THISRC=99
      ;;
  esac
  return ${THISRC}
}

[ $# -eq 0 ] && set -- "--help"

while [ $# -ne 0 ] ; do
  CUR_PARAMETER="$1"
  shift

  case ${CUR_PARAMETER} in
  
    -h | --help )
      grep "^#h#" $0 | cut -c4- 
      die 0
      ;;

    on | yes | enable )
      LogMsg "Enabling Monitor mode for the interface \"${WLAN_INTERFACE}\" now ..."
      enable_monitor_mode
      ;;
   
    off | no | disable )
      LogMsg "Disabling Monitor mode for the interface \"${WLAN_INTERFACE}\" now ..."
      disable_monitor_mode
      ;;

    status )
      LogMsg "Retrieving the status of the Monitor mode for the interface \"${WLAN_INTERFACE}\" ..."
      read_monitor_mode
      THISRC=$?
      ;;
    
    if=* )
      WLAN_INTERFACE="${CUR_PARAMETER#*=}"
      case ${WLAN_INTERFACE} in
        "" )
          die 5 "The parameter \"${CUR_PARAMETER}\" is incomplete"
          ;;

        default )
          WLAN_INTERFACE="${DEFAULT_WLAN_INTERFACE}"
          ;;
          
      esac
      LogMsg "Using the WLAN interface \"${WLAN_INTERFACE}\" "
      ;;
      
    * ) 
      CUR_COMMAND="${CUR_PARAMETER}"
      CUR_COMMAND_PARAMETER="$*"
      break
      ;;

  esac

done

if [ "${CUR_COMMAND}"x != ""x ] ; then

  LogMsg "Enabling Monitor mode for the interface \"${WLAN_INTERFACE}\" now ..."
  enable_monitor_mode
  read_monitor_mode
  
  LogMsg "Executing now \"${CUR_COMMAND}  ${CUR_COMMAND_PARAMETER}\" ..."

  "${CUR_COMMAND}"  ${CUR_COMMAND_PARAMETER}
  THISRC=$?

  LogMsg "Disabling Monitor mode for the interface \"${WLAN_INTERFACE}\" now ..."
  disable_monitor_mode
  read_monitor_mode
fi

die ${THISRC}
