| #!/bin/bash |
| |
| #**************************************************************************** |
| # tools/simwifi/sim_wifi.sh |
| # |
| # SPDX-License-Identifier: Apache-2.0 |
| # |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. The |
| # ASF licenses this file to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance with the |
| # License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations |
| # under the License. |
| # |
| #**************************************************************************** |
| # |
| |
| NUTTX_BR_IF="nuttx0" |
| RUN_DIR="/var/run/simwifi" |
| LINK_DIR="/usr/bin" |
| CUR_DIR="" |
| DBG_LEVEL=1 |
| |
| WPA_PID_FILE="$RUN_DIR/wpa_supplicant.pid" |
| WPA_CONF_FILE="$RUN_DIR/wpa_supplicant.conf" |
| HOSTAPD_PID_FILE="$RUN_DIR/hostapd.pid" |
| HOSTAPD_CONF_FILE="$RUN_DIR/hostapd.conf" |
| DNSMASQ_PID="$RUN_DIR/dnsmasq.pid" |
| DNSMASQ_CONF="$RUN_DIR/dnsmasq.conf" |
| UDHCPC_PID="$RUN_DIR/udhcpc.pid" |
| UDHCPC_SCRIPT="/var/udhcpc.script" |
| |
| LOG_FILE="$RUN_DIR/simwifi.log" |
| STATE_FILE="$RUN_DIR/simwifi.state" |
| DEFCONF_FILE="$RUN_DIR/simwifi.conf" |
| |
| DHCP_CLIENT=$(which udhcpc) |
| DNSMASQ=$(which dnsmasq) |
| WPA_SUPPLICANT=$(which wpa_supplicant) |
| HOSTAPD=$(which hostapd) |
| |
| # print the debug message |
| sw_dbg() |
| { |
| [ $1 -ge $DBG_LEVEL ] && { |
| echo "$2" |
| } |
| } |
| |
| # get var from the file |
| # $1:key $2:file |
| get_var() |
| { |
| cat $2 | grep $1 | awk -F':' '{print $2}' |
| } |
| |
| check_state() |
| { |
| old_state=$(get_var state $STATE_FILE) |
| sw_dbg 1 "new state:$1, old_state:$old_state" |
| |
| if [ "$1" = "$old_state" ]; then |
| sw_dbg 1 "cur_state is $1" |
| exit 0 |
| fi |
| } |
| |
| # set simwifi state |
| set_state() |
| { |
| state=$1 |
| wlan_if=$2 |
| br_if=$3 |
| wan_if=$4 |
| sw_dbg 1 "[set_state] new state:$1" |
| |
| if [ "$state" != "SW_INIT" -a "$state" != "SW_HWSIM" -a \ |
| "$state" != "SW_NET" -a "$state" != "SW_STA" -a \ |
| "$state" != "SW_AP" -a "$state" != "SW_STAAP" ]; then |
| echo "no state: $1" |
| exit -1 |
| fi |
| |
| sw_dbg 1 "state:$state wlan_if:$wlan_if, br_if:$br_if wan_if:$wan_if" |
| |
| echo "state:$state" > $STATE_FILE |
| [ -n "$wlan_if" ] && echo "wlan:$wlan_if" >> $STATE_FILE |
| [ -n "$br_if" ] && echo "br:$br_if" >> $STATE_FILE |
| [ -n "$wan_if" ] && echo "wan:$wan_if" >> $STATE_FILE |
| } |
| |
| # recover the simwifi state to SW_INIT |
| |
| recovery_to_init() |
| { |
| cur_state=$(get_var state $STATE_FILE) |
| wlan_if=$(get_var wlan $STATE_FILE) |
| br_if=$(get_var br $STATE_FILE) |
| |
| sw_dbg 1 "[recovery_to_init] cur_s:$cur_state" |
| case $cur_state in |
| SW_INIT) ;; |
| SW_HWSIM) stop_hwsim;; |
| SW_STAAP) stop_staap;; |
| SW_NET) stop_net $wlan_if;; |
| SW_STA) stop_sta;; |
| SW_AP) stop_ap $wlan_if;; |
| *) set_state SW_INIT;; |
| esac |
| } |
| |
| # Get the absolute pathname of sim_wifi.sh |
| |
| get_script_path() |
| { |
| SOURCE=$1 |
| |
| while [ -h "$SOURCE" ]; do |
| SOURCE=$(readlink $SOURCE) |
| done |
| |
| CUR_DIR=$(cd $(dirname $SOURCE) && pwd) |
| } |
| |
| # Copy the configure file to the $RUN_DIR |
| |
| init_env() |
| { |
| sw_dbg 1 "init env" |
| |
| [ -f "$STATE_FILE" ] && { |
| check_hwsim_mode |
| recovery_to_init |
| } |
| |
| mkdir -p $RUN_DIR |
| touch $STATE_FILE |
| |
| if [ "$1" = "hwsim" ]; then |
| cp -fr $CUR_DIR/hostapd_hwsim.conf $HOSTAPD_CONF_FILE |
| cp -fr $CUR_DIR/wpa_supplicant_hwsim.conf $WPA_CONF_FILE |
| else |
| cp -fr $CUR_DIR/hostapd.conf $HOSTAPD_CONF_FILE |
| cp -fr $CUR_DIR/wpa_supplicant.conf $WPA_CONF_FILE |
| fi |
| |
| cp -fr $CUR_DIR/dnsmasq.conf $DNSMASQ_CONF |
| cp -fr $CUR_DIR/udhcpc.script $UDHCPC_SCRIPT |
| chmod +x $UDHCPC_SCRIPT |
| } |
| |
| # Rename the interface name |
| |
| rename_ifdev() |
| { |
| old_name=$1 |
| new_name=$2 |
| |
| ifconfig $old_name down && ip link set $old_name name $new_name |
| ifconfig $new_name up |
| } |
| |
| kill_service() |
| { |
| service_name=$(basename $1 .pid) |
| sw_dbg 1 "kill $service_name" |
| if [ -f "$1" ]; then |
| pid=$(cat $1) |
| kill -9 $pid |
| rm $1 |
| else |
| sw_dbg 1 "$1 isn't existed." |
| killall $service_name |
| fi |
| } |
| |
| stop_wpa() |
| { |
| kill_service $WPA_PID_FILE |
| } |
| |
| stop_hostapd() |
| { |
| kill_service $HOSTAPD_PID_FILE |
| } |
| |
| start_hostapd() |
| { |
| sw_dbg 1 "start ap on $1" |
| |
| #Waiting 1s. If not, the hostapd starting maybe fail on switching mode. |
| |
| sleep 1 |
| $HOSTAPD -B -i$1 -P $HOSTAPD_PID_FILE $HOSTAPD_CONF_FILE -t &>>$LOG_FILE |
| } |
| |
| start_wpa() |
| { |
| sw_dbg 1 "start sta on $1" |
| |
| #Waiting 1s. If not, the wap_supplicant starting maybe fail on switching mode. |
| |
| sleep 1 |
| $WPA_SUPPLICANT -B -c $WPA_CONF_FILE -i$1 -P $WPA_PID_FILE &>>$LOG_FILE |
| } |
| |
| start_udhcpc() |
| { |
| sw_dbg 1 "start dhcp client on $1" |
| |
| [ -n "$2" ] && script_opt=" -s $UDHCPC_SCRIPT" |
| |
| $DHCP_CLIENT -i $1 -p $UDHCPC_PID $script_opt &>>$LOG_FILE & |
| } |
| |
| stop_udhcpc() |
| { |
| kill_service $UDHCPC_PID |
| } |
| |
| start_bridge() |
| { |
| sw_dbg 1 "start bridge to $1" |
| $CUR_DIR/../simhostroute.sh $1 on &>>$LOG_FILE |
| } |
| |
| stop_bridge() |
| { |
| sw_dbg 1 "stop bridge to $1" |
| sw_dbg 1 "Warning: The $NUTTX_BR_IF will be deleted!" |
| $CUR_DIR/../simhostroute.sh $1 off &>>$LOG_FILE |
| } |
| |
| start_dhcp_server() |
| { |
| sw_dbg 1 "start dhcp server on $1" |
| dbg_option=$($DNSMASQ --help|grep log-debug | awk '{print $1}') |
| |
| $DNSMASQ -i$1 -C $DNSMASQ_CONF $dbg_option -x $DNSMASQ_PID &>>$LOG_FILE |
| } |
| |
| stop_dhcp_server() |
| { |
| kill_service $DNSMASQ_PID |
| } |
| |
| check_hwsim_mode() |
| { |
| cur_state=$(get_var state $STATE_FILE) |
| |
| sw_dbg 1 "[check_hwsim_mode]state: $cur_state" |
| if [ "$cur_state" = "SW_HWSIM" ]; then |
| sw_dbg 1 "cur_state is hwsim mode. \ |
| Don't set the sta/ap mode." |
| exit 0 |
| fi |
| } |
| |
| start_hwsim() |
| { |
| sta_if=${1:-wlan0} |
| ap_if=${2:-wlan1} |
| |
| sw_dbg 1 "start hwsim on $sta_if $ap_if" |
| |
| init_env hwsim |
| start_hostapd $ap_if |
| start_wpa $sta_if |
| start_dhcp_server $NUTTX_BR_IF |
| |
| set_state SW_HWSIM |
| } |
| |
| stop_hwsim() |
| { |
| stop_wpa |
| stop_hostapd |
| |
| stop_dhcp_server |
| |
| set_state SW_INIT |
| } |
| |
| start_net() |
| { |
| init_env |
| start_wpa $1 |
| start_udhcpc $1 |
| start_bridge $1 |
| start_dhcp_server $NUTTX_BR_IF |
| |
| set_state SW_NET $1 $NUTTX_BR_IF $1 |
| } |
| |
| # Warning:The function will delete nuttx0 |
| |
| stop_net() |
| { |
| stop_wpa |
| stop_udhcpc |
| stop_bridge $1 |
| stop_dhcp_server |
| |
| set_state SW_INIT |
| } |
| |
| start_sta() |
| { |
| [ -z "$(ifconfig | grep "$NUTTX_BR_IF")" ] && { |
| sw_dbg 1 "Please ensure that the $NUTTX_BR_IF is existed." |
| exit -2 |
| } |
| |
| check_state SW_STA |
| check_state SW_STAAP |
| |
| init_env |
| start_wpa $1 |
| start_udhcpc $1 s |
| start_dhcp_server $NUTTX_BR_IF |
| |
| set_state SW_STA $1 $NUTTX_BR_IF; |
| |
| exit 0 |
| } |
| |
| del_gw_wlan() |
| { |
| wlan_if=$1 |
| router=$(ip route show | grep default | grep $wlan_if) |
| |
| [ -n "$router" ] && { |
| ip route del $router |
| sw_dbg 1 "del the default router on $wlan_if" |
| } |
| |
| ifconfig $wlan_if 0.0.0.0 |
| } |
| |
| stop_sta() |
| { |
| stop_wpa |
| stop_udhcpc |
| stop_dhcp_server |
| |
| #check and delete default on wlan0 |
| |
| wlan_if=$(get_var wlan $STATE_FILE) |
| del_gw_wlan $wlan_if |
| |
| set_state SW_INIT |
| } |
| |
| start_ap() |
| { |
| [ -z "$1" ] && { |
| echo "Missing parameter wlan interface." |
| exit -1 |
| } |
| |
| [ -z "$2" ] && { |
| [ -z "$(ifconfig | grep "$NUTTX_BR_IF")" ] && { |
| echo "Missing parameter wan interface." |
| echo "Please ensure that the $NUTTX_BR_IF is existed." |
| exit -2 |
| } |
| |
| wan_if="" |
| } || { |
| wan_if=$2 |
| } |
| |
| check_state SW_AP |
| check_state SW_STAAP |
| |
| init_env |
| start_hostapd $1 |
| |
| # nuttx0 doesn't exist and wan_if is configured. |
| |
| [ -z "$(ifconfig | grep "$NUTTX_BR_IF")" -a -n "$wan_if" ] && { |
| start_bridge $wan_if |
| } |
| |
| ip link set dev $1 master $NUTTX_BR_IF |
| start_dhcp_server $NUTTX_BR_IF |
| |
| set_state SW_AP $1 $wan_if; |
| |
| exit 0 |
| } |
| |
| stop_ap() |
| { |
| stop_hostapd |
| [ -z "$2" ] || stop_bridge $2 |
| |
| sw_dbg 1 "stop_ap $1" |
| ip link set dev $1 nomaster |
| stop_dhcp_server |
| |
| set_state SW_INIT |
| } |
| |
| check_ifname() |
| { |
| [ -z "$(ifconfig | grep "$1")" ] && { |
| echo "The $1 does not exist." |
| exit -1 |
| } |
| } |
| |
| start_staap() |
| { |
| sta_if=${1:-wlan0} |
| ap_if=${2:-wlan1} |
| sw_dbg 1 "start staap $sta_if $ap_if" |
| |
| for i in $sta_if $ap_if $NUTTX_BR_IF; do |
| check_ifname $i |
| done |
| |
| check_state SW_STAAP |
| |
| init_env |
| start_hostapd $ap_if |
| |
| sleep 1 |
| start_wpa $sta_if |
| |
| ip link set dev $ap_if master $NUTTX_BR_IF |
| |
| start_udhcpc $sta_if |
| start_dhcp_server $NUTTX_BR_IF |
| |
| set_state SW_STAAP "$sta_if,$ap_if" $NUTTX_BR_IF |
| } |
| |
| stop_staap() |
| { |
| stop_wpa |
| stop_hostapd |
| |
| stop_udhcpc |
| stop_dhcp_server |
| ip link set dev wlan1 nomaster |
| |
| set_state SW_INIT |
| } |
| |
| show_process() |
| { |
| ps -ef | grep "$1 " | grep -v grep |
| } |
| |
| show_status() |
| { |
| #1.env conf |
| [ -d "$RUN_DIR" ] && { |
| echo "$RUN_DIR" |
| ls $RUN_DIR |
| } |
| |
| #2. key services |
| echo -e "\nservices list" |
| for i in wpa_supplicant hostapd dnsmasq udhcpc; do |
| show_process $i |
| done |
| |
| #3. bridge nuttx0 info |
| [ -n "$(ifconfig | grep $NUTTX_BR_IF)" ] && { |
| echo -e "\nbridge $NUTTX_BR_IF" |
| ip link show master $NUTTX_BR_IF |
| } |
| |
| #4.show DEFCONF_FILE |
| echo -e "\ndefault config" |
| cat $DEFCONF_FILE |
| |
| #5. show state |
| echo "" |
| cat $STATE_FILE |
| |
| #6. show router |
| echo "" |
| ip route show |
| |
| #7. show radio state |
| echo "radio status" |
| rfkill list |
| |
| #8. show networkmanager wifi status |
| echo "networkmanager wifi status" |
| nmcli radio wifi |
| } |
| |
| # $1 is the default wan interface for start_sta |
| # $2 is the simwifi mode, (rnc/hwsim) |
| |
| init() |
| { |
| [ -z "$1" ] && { |
| echo "Missing the default wan interface." |
| exit -1 |
| } |
| |
| [ -z "$2" ] && { |
| echo "Missing the simwifi mode." |
| exit -2 |
| } |
| |
| init_env |
| |
| ln -s $CUR_DIR/sim_wifi.sh $LINK_DIR/sim_wifi.sh |
| |
| echo "defwan:$1" > $DEFCONF_FILE |
| [ -n "$1" -a -n "$(ifconfig | grep $1)" ] && start_bridge $1 |
| |
| echo "mode:$2" >> $DEFCONF_FILE |
| [ "$2" = "hwsim" ] && modprobe mac80211_hwsim |
| |
| # Turn off the wifi of networkmanager. |
| nmcli radio wifi off |
| |
| # open the radio by rfkill |
| id_list=$(rfkill list | grep phy | awk -F':' '{print $1}') |
| for id in $id_list; do |
| rfkill unblock $id; |
| done |
| |
| set_state SW_INIT "" $NUTTX_BR_IF $1 |
| } |
| |
| clean() |
| { |
| [ -z "$1" ] && { |
| echo "Missing the default wan interface." |
| exit -1 |
| } |
| |
| recovery_to_init |
| |
| rm $LINK_DIR/sim_wifi.sh |
| |
| cur_mode=$(get_var mode $DEFCONF_FILE) |
| [ "$cur_mode" = "hwsim" ] && modprobe -r mac80211_hwsim |
| |
| echo "defwan:$1" > $DEFCONF_FILE |
| [ -n "$1" -a -n "$(ifconfig | grep $1)" ] && stop_bridge $1 |
| |
| rm -fr $RUN_DIR |
| rm -f $UDHCPC_SCRIPT |
| |
| # Turn on the wifi of networkmanager. |
| nmcli radio wifi on |
| |
| } |
| |
| usage() |
| { |
| echo "$(basename $SOURCE) (rename <old> <new> |" |
| echo -e "\t init <wan> <mode> |clean <wan> |" |
| echo -e "\t start_wpa <wlan0> |stop_wpa |" |
| echo -e "\t start_hostapd <wlan0> |stop_hostapd |" |
| echo -e "\t start_udhcpc <wlan0> |stop_udhcpc |" |
| echo -e "\t start_dhcp <wlan0> |stop_dhcp |" |
| echo -e "\t start_hwsim |stop_hwsim |up_hwsim |" |
| echo -e "\t start_staap |stop_staap |" |
| echo -e "\t start_net <wlan0> |stop_net <wlan0> |" |
| echo -e "\t start_sta <wlan0> |stop_sta |" |
| echo -e "\t start_ap <wlan0> [eth0] |stop_ap <wlan0> [eth0] |" |
| echo -e "\t start_bridge <eth0> |stop_bridge <eth0> |" |
| echo -e "\t show | help)" |
| } |
| |
| # locate the directory of the sim_wifi.sh. |
| |
| get_script_path $0 |
| |
| case $1 in |
| init) init $2 $3;; |
| clean) clean $2;; |
| start_bridge) start_bridge $2;; |
| stop_bridge) stop_bridge $2;; |
| start_hwsim) start_hwsim $2 $3;; |
| stop_hwsim) stop_hwsim;; |
| up_hwsim) ifconfig hwsim0 up;; |
| start_wpa) start_wpa $2;; |
| stop_wpa) stop_wpa;; |
| start_hostapd) start_hostapd $2;; |
| stop_hostapd) stop_hostapd;; |
| rename) rename_ifdev $2 $3;; |
| start_udhcpc) start_udhcpc $2;; |
| stop_udhcpc) stop_udhcpc;; |
| start_dhcp) start_dhcp_server $2;; |
| stop_dhcp) stop_dhcp_server;; |
| start_net) start_net $2;; |
| stop_net) stop_net $2;; |
| start_sta) start_sta $2;; |
| stop_sta) stop_sta;; |
| start_ap) start_ap $2 $3;; |
| stop_ap) stop_ap $2 $3;; |
| start_staap) start_staap;; |
| stop_staap) stop_staap;; |
| show) show_status;; |
| help|*) usage;; |
| esac |