#!/bin/bash LANG=C PING_COUNT=2 CHECK_INTERVAL_SEC=120 FORCE_RECONNECT_PING_NG_COUNT=2 FORCE_REBOOT_PING_NG_COUNT=$(( $FORCE_RECONNECT_PING_NG_COUNT+2 )) CONFIG_FILE_EXT=_connection-recover.conf CONFIG_FILE_DIR=/etc/connection-recover/ SYMLINK_CONF_FILE=/etc/ModemManager/symlink.conf NMCLI_UP_TIMEOUT_SEC=150 RESTART_SIM_NOT_FOUND_COUNT=2 REGEX_GSM_TTY="^gsm-tty" CONNECTING_COUNT_FOR_RECONNECT=3 active_connection_exist() { nmcli -f NAME connection | sed -e 's/ *$//' | grep -x -q ${CONNECTION} if [ $? -eq 0 ]; then return 0 fi return 1 } check_symlink_conf_line() { while read line do line="`echo ${line} | sed 's/ //g'`" if [ "${line}" = ${SYMLINK_MM_PARAM} ]; then return 0 fi done < $SYMLINK_CONF_FILE return 1 } check_use_symlink_device() { if [ ! -L /dev/${SYMLINKDEVICE} ]; then return 1 fi if [ ! -e "$SYMLINK_CONF_FILE" ]; then return 1 fi if [ -z "$SYMLINKDEVICE" ]; then return 1 fi if [ -z "$SYMLINK_MM_PARAM" ]; then return 1 fi check_symlink_conf_line return $? } get_connection_status() { nmcli -f DEVICE,STATE device | grep "$DEVICE" } reconnect() { logger -t connection-recover "$DEVICE reconnect start... " nmcli connection down ${CONNECTION} > /dev/null 2>&1 sleep 5 timeout -sKILL ${NMCLI_UP_TIMEOUT_SEC} nmcli connection up ${CONNECTION} > /dev/null 2>&1 result=$? if [ ${result} -eq 0 ]; then logger -t connection-recover "$DEVICE reconnect success" else logger -t connection-recover "$DEVICE reconnect fail: ${result}" return -1 fi return 0 } check_route() { ip route get ${PING_DEST_IP} | grep ${NETWORK_IF} > /dev/null 2>&1 } is_connect() { ping -s 1 -c ${PING_COUNT} -w 10 -I ${NETWORK_IF} ${PING_DEST_IP} > /dev/null 2>&1 if [ $? -eq 0 ]; then return 0 else logger -t connection-recover "$DEVICE ping fail" fi return 1 } clear_config() { PRODUCT_NAME="" PING_DEST_IP="" DEVICE="" TYPE="" NETWORK_IF="" SYMLINKDEVICE="" SYMLINK_MM_PARAM="" WWAN_FORCE_RESTART_COUNT="" REBOOT_IF_SIM_NOT_FOUND="" } read_config_file() { . ${CONFIG_FILE} if [ ! -n "$PRODUCT_NAME" ]; then logger -t connection-recover "$1 is PRODUCT_NAME not set" return 1 fi if [ ! -n "$PING_DEST_IP" ]; then logger -t connection-recover "$1 is PING_DEST_IP not set" return 1 fi if [ ! -n "$DEVICE" ]; then logger -t connection-recover "$1 is DEVICE not set" return 1 fi if [ ! -n "$TYPE" ]; then logger -t connection-recover "$1 is TYPE not set" return 1 fi if [ ! -n "$NETWORK_IF" ]; then logger -t connection-recover "$1 is NETWORK_IF not set" return 1 fi if [ ! -n "$FORCE_REBOOT" ]; then logger -t connection-recover "$1 is FORCE_REBOOT not set" return 1 fi OLD_IFS=$IFS IFS="," for CHECK_PRODUCT in $PRODUCT_NAME; do grep ${CHECK_PRODUCT} /proc/device-tree/model -q -w if [ $? -eq 0 ]; then IFS=$OLD_IFS return 0 fi done IFS=$OLD_IFS return 1 } load_config() { OLD_IFS=$IFS IFS=" " for CONFIG_FILE in `find ${CONFIG_FILE_DIR} -name "*${CONFIG_FILE_EXT}"`; do clear_config if ! read_config_file; then continue else IFS=$OLD_IFS return fi done IFS=$OLD_IFS logger -t connection-recover "error: config file is not found" exit 1 } load_config PING_NG_COUNT=0 SIM_NOT_FOUND_COUNT=0 WWAN_RESTART_COUNT=0 CONNECTING_COUNT=0 if [ -z "$WWAN_FORCE_RESTART_COUNT" ]; then WWAN_FORCE_RESTART_COUNT=1 fi DEFAULT_DEVICE=${DEVICE} while true; do sleep ${CHECK_INTERVAL_SEC} check_use_symlink_device if [ $? -eq 0 ]; then DEVICE=${SYMLINKDEVICE} else DEVICE=${DEFAULT_DEVICE} fi CONNECTION=$(basename "$CONFIG_FILE" "$CONFIG_FILE_EXT") if [[ -z "$CONNECTION" || $CONNECTION =~ $REGEX_GSM_TTY ]]; then CONNECTION="${TYPE}-${DEVICE}" fi if [ -z "$CONNECTION" ]; then continue fi active_connection_exist if [ $? -eq 0 ]; then PING_STATUS=1 STATUS=`get_connection_status` case ${STATUS} in *disconnected*|*failed*|*unknown*|"*connection failed*") SIM_NOT_FOUND_COUNT=0 CONNECTING_COUNT=0 reconnect if [ $? -eq 0 ]; then continue fi ;; *connected*) SIM_NOT_FOUND_COUNT=0 CONNECTING_COUNT=0 is_connect PING_STATUS=$? if [ $PING_STATUS -ne 0 ]; then # if reboot or restart wwan, do not reconnect PING_NG_COUNT_TMP=$(( $PING_NG_COUNT+1 )) if [ $PING_NG_COUNT_TMP -lt $FORCE_RECONNECT_PING_NG_COUNT ]; then reconnect elif [ "$FORCE_REBOOT" = "TRUE" ]; then if [ $PING_NG_COUNT_TMP -lt $FORCE_REBOOT_PING_NG_COUNT ]; then reconnect fi fi else WWAN_RESTART_COUNT=0 fi ;; *connecting*) SIM_NOT_FOUND_COUNT=0 CONNECTING_COUNT=$((CONNECTING_COUNT + 1)) if [ $CONNECTING_COUNT -ge $CONNECTING_COUNT_FOR_RECONNECT ]; then logger -t connection-recover "reconnect because connecting status occurred twice" CONNECTING_COUNT=0 reconnect fi continue ;; *deactivating*|*unmanaged*) SIM_NOT_FOUND_COUNT=0 CONNECTING_COUNT=0 continue ;; *unavailable*|*) CONNECTING_COUNT=0 if [ "$REBOOT_IF_SIM_NOT_FOUND" != "TRUE" ] ; then continue fi SIM_NOT_FOUND_COUNT=$((SIM_NOT_FOUND_COUNT + 1)) logger -t connection-recover "sim not found. status: ${STATUS}" if [ $SIM_NOT_FOUND_COUNT -ge $RESTART_SIM_NOT_FOUND_COUNT ] ; then logger -t connection-recover "exec system reboot cause sim not found" reboot fi esac if [ $PING_STATUS -ne 0 ]; then PING_NG_COUNT=$(( $PING_NG_COUNT+1 )) if [ "$FORCE_REBOOT" = "TRUE" ]; then if [ $PING_NG_COUNT -ge $FORCE_REBOOT_PING_NG_COUNT ]; then logger -t connection-recover "exec system reboot" reboot fi fi if [ $PING_NG_COUNT -ge $FORCE_RECONNECT_PING_NG_COUNT ]; then WWAN_RESTART_COUNT=$((WWAN_RESTART_COUNT+1)) if [ $WWAN_RESTART_COUNT -ge $WWAN_FORCE_RESTART_COUNT ]; then logger -t connection-recover "exec wwan-force-restart" wwan-force-restart "$CONNECTION" WWAN_RESTART_COUNT=0 else logger -t connection-recover "exec wwan-restart" wwan-force-restart "$CONNECTION" airplane fi fi else PING_NG_COUNT=0 fi fi done