| #!/bin/sh |
| |
| # SPDX-License-Identifier: GPL-2.0-or-later |
| # |
| # Copyright (C) 2013-2016 Aleksander Morgado <aleksander@aleksander.es> |
| # |
| # Based on libqmi's qmi-network script |
| # |
| |
| print_usage () |
| { |
| echo "usage: $0 [OPTIONS] [DEVICE] [COMMAND]" |
| } |
| |
| help () |
| { |
| echo "Usage: mbim-network [OPTIONS] [DEVICE] [COMMAND]" |
| echo |
| echo "Simple network management of MBIM devices" |
| echo |
| echo "Commands:" |
| echo " start Start network connection" |
| echo " stop Stop network connection" |
| echo " status Query network connection status" |
| echo |
| echo "Options:" |
| echo " --profile=[PATH] Use the profile in the specified path" |
| echo " --help, -h Show help options" |
| echo " --version Show version" |
| echo |
| echo "Notes:" |
| echo |
| echo " 1) [DEVICE] is given as the full path to the cdc-wdm character" |
| echo " device, e.g.:" |
| echo " /dev/cdc-wdm0" |
| echo |
| echo " 2) The mbim-network script requires a profile to work. Unless" |
| echo " explicitly specified with \`--profile', the file is assumed to" |
| echo " be available in the following path:" |
| echo " /etc/mbim-network.conf" |
| echo |
| echo " 3) The APN to use should be configured in the profile, in the" |
| echo " following way (e.g. assuming APN is called 'internet'):" |
| echo " APN=internet" |
| echo |
| echo " 4) Optional APN user/password strings may be given in the" |
| echo " following way:" |
| echo " APN_USER=user" |
| echo " APN_PASS=password" |
| echo |
| echo " 5) If APN user/password is specified, the authentication protocol" |
| echo " to use (one of PAP, CHAP or MSCHAPV2) must also be specified in" |
| echo " the following way:" |
| echo " APN_AUTH=protocol" |
| echo |
| echo " 6) If you want to instruct the mbim-network script to use the" |
| echo " mbim-proxy setup, you can do so by configuring the following line" |
| echo " in the profile:" |
| echo " PROXY=yes" |
| echo |
| echo " 7) Once the mbim-network script reports a successful connection" |
| echo " you still need to run a DHCP client on the associated WWAN network" |
| echo " interface." |
| echo |
| } |
| |
| version () |
| { |
| echo "mbim-network @VERSION@" |
| echo "Copyright (C) 2013-2021 Aleksander Morgado" |
| echo "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl-2.0.html>" |
| echo "This is free software: you are free to change and redistribute it." |
| echo "There is NO WARRANTY, to the extent permitted by law." |
| echo |
| } |
| |
| # Basic options |
| if [ $# -lt 2 ]; then |
| if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then |
| help |
| exit 0 |
| elif [ "$1" = "--version" ]; then |
| version |
| exit 0 |
| fi |
| |
| echo "error: missing arguments" 1>&2 |
| print_usage |
| exit 255 |
| fi |
| |
| # Defaults |
| PROFILE_FILE=/etc/mbim-network.conf |
| |
| # Device + Command with options; options given first |
| while [ $# -gt 2 ]; do |
| OPT="$1" |
| shift |
| |
| case "$OPT" in |
| "--") |
| break 2;; |
| "--profile") |
| if [ $# -gt 2 ]; then |
| PROFILE_FILE="$1" |
| shift |
| else |
| PROFILE_FILE="" |
| fi |
| ;; |
| "--profile="*) |
| PROFILE_FILE="${OPT#*=}";; |
| *) |
| echo >&2 "Invalid option: $OPT" |
| print_usage |
| exit 255;; |
| esac |
| done |
| |
| if [ -z "$PROFILE_FILE" ]; then |
| echo "error: empty profile path given" 1>&2 |
| print_usage |
| exit 255 |
| fi |
| |
| if [ $# -ne 2 ] || [ "$1" = "--*" ] || [ "$2" = "--*" ]; then |
| echo "error: missing arguments" 1>&2 |
| print_usage |
| exit 255 |
| fi |
| |
| DEVICE=$1 |
| COMMAND=$2 |
| |
| STATE_FILE=/tmp/mbim-network-state-`basename $DEVICE` |
| |
| load_profile () |
| { |
| if [ -f "$PROFILE_FILE" ]; then |
| echo "Loading profile at ${PROFILE_FILE}..." |
| . $PROFILE_FILE |
| |
| if [ -n "$APN" ]; then |
| echo " APN: $APN" |
| else |
| echo " APN: unset" |
| fi |
| |
| if [ -n "$APN_AUTH" ]; then |
| echo " APN auth protocol: $APN_AUTH" |
| else |
| echo " APN auth protocol: unset" |
| fi |
| |
| if [ -n "$APN_USER" ]; then |
| echo " APN user: $APN_USER" |
| if [ -z "$APN_AUTH" ]; then |
| echo "error: APN_USER in the profile requires APN_AUTH" 1>&2 |
| exit 32 |
| fi |
| else |
| echo " APN user: unset" |
| fi |
| |
| if [ -n "$APN_PASS" ]; then |
| echo " APN password: $APN_PASS" |
| if [ -z "$APN_USER" ]; then |
| echo "error: APN_PASS in the profile requires APN_USER" 1>&2 |
| exit 32 |
| fi |
| else |
| echo " APN password: unset" |
| fi |
| |
| if [ "$PROXY" = "yes" ]; then |
| echo " mbim-proxy: $PROXY" |
| PROXY_OPT='--device-open-proxy' |
| else |
| echo " mbim-proxy: no" |
| fi |
| else |
| echo "Profile at '$PROFILE_FILE' not found..." |
| fi |
| } |
| |
| save_state () |
| { |
| KEY=$1 |
| VAL=$2 |
| |
| if [ -n "${PROXY_OPT}" ]; then |
| return |
| fi |
| |
| echo "Saving state at ${STATE_FILE}... ($KEY: $VAL)" |
| |
| if [ -f "$STATE_FILE" ]; then |
| PREVIOUS=`cat $STATE_FILE` |
| PREVIOUS=`echo "$PREVIOUS" | grep -v $KEY` |
| if [ -n "$PREVIOUS" ]; then |
| echo $PREVIOUS > $STATE_FILE |
| else |
| rm $STATE_FILE |
| fi |
| fi |
| |
| if [ -n "$VAL" ]; then |
| echo "$KEY=\"$VAL\"" >> $STATE_FILE |
| fi |
| } |
| |
| load_state () |
| { |
| if [ -n "${PROXY_OPT}" ]; then |
| return |
| fi |
| |
| if [ -f "$STATE_FILE" ]; then |
| echo "Loading previous state from ${STATE_FILE}..." |
| . $STATE_FILE |
| if [ -n "$TRID" ]; then |
| echo " Previous Transaction ID: $TRID" |
| fi |
| fi |
| } |
| |
| clear_state () |
| { |
| if [ -n "${PROXY_OPT}" ]; then |
| return |
| fi |
| |
| echo "Clearing state at ${STATE_FILE}..." |
| rm -f $STATE_FILE |
| } |
| |
| # |
| # $ sudo mbimcli -d /dev/cdc-wdm0 --connect="Internet" --no-close |
| # [/dev/cdc-wdm0] Successfully connected |
| # [/dev/cdc-wdm0] Connection status: |
| # Session ID: '0' |
| # Activation state: 'activated' |
| # Voice call state: 'none' |
| # IP type: 'ipv4' |
| # Context type: 'internet' |
| # Network error: 'unknown' |
| # |
| connect () |
| { |
| # Always try to connect using a fresh session |
| if [ -z "${PROXY_OPT}" ]; then |
| if [ -n "$TRID" ]; then |
| # This will implicitly close the previous session |
| mbimcli -d $DEVICE --no-open=$TRID |
| clear_state |
| fi |
| fi |
| |
| if [ -z "${PROXY_OPT}" ]; then |
| EXTRA_OPT="--no-close" |
| else |
| EXTRA_OPT="${PROXY_OPT}" |
| fi |
| |
| SUBSCRIBER_READY_CMD="mbimcli -d $DEVICE --query-subscriber-ready-status ${EXTRA_OPT}" |
| echo "Querying subscriber ready status '$SUBSCRIBER_READY_CMD'..." |
| |
| SUBSCRIBER_READY_OUT=`$SUBSCRIBER_READY_CMD` |
| echo $SUBSCRIBER_READY_OUT |
| |
| if [ -z "${PROXY_OPT}" ]; then |
| TRID=`echo "$SUBSCRIBER_READY_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"` |
| EXTRA_OPT="--no-open=$TRID --no-close" |
| else |
| EXTRA_OPT="${PROXY_OPT}" |
| fi |
| |
| REGISTRATION_STATE_CMD="mbimcli -d $DEVICE --query-registration-state ${EXTRA_OPT}" |
| echo "Querying registration state '$REGISTRATION_STATE_CMD'..." |
| |
| REGISTRATION_STATE_OUT=`$REGISTRATION_STATE_CMD` |
| echo $REGISTRATION_STATE_OUT |
| |
| if [ -z "${PROXY_OPT}" ]; then |
| TRID=`echo "$REGISTRATION_STATE_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"` |
| EXTRA_OPT="--no-open=$TRID --no-close" |
| else |
| EXTRA_OPT="${PROXY_OPT}" |
| fi |
| |
| ATTACH_CMD="mbimcli -d $DEVICE --attach-packet-service ${EXTRA_OPT}" |
| echo "Attaching to packet service with '$ATTACH_CMD'..." |
| |
| ATTACH_OUT=`$ATTACH_CMD` |
| echo $ATTACH_OUT |
| |
| if [ -z "${PROXY_OPT}" ]; then |
| TRID=`echo "$ATTACH_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"` |
| EXTRA_OPT="--no-open=$TRID --no-close" |
| else |
| EXTRA_OPT="${PROXY_OPT}" |
| fi |
| |
| CONNECT_ARGS="apn='$APN'" |
| if [ -n "$APN_AUTH" ]; then |
| CONNECT_ARGS="${CONNECT_ARGS},auth='$APN_AUTH'" |
| if [ -n "$APN_USER" ]; then |
| CONNECT_ARGS="${CONNECT_ARGS},username='$APN_USER'" |
| if [ -n "$APN_PASS" ]; then |
| CONNECT_ARGS="${CONNECT_ARGS},password='$APN_PASS'" |
| fi |
| fi |
| fi |
| |
| CONNECT_CMD="mbimcli -d $DEVICE --connect=$CONNECT_ARGS ${EXTRA_OPT}" |
| echo "Starting network with '$CONNECT_CMD'..." |
| |
| CONNECT_OUT=`$CONNECT_CMD` |
| if [ $? -eq 0 ]; then |
| echo "Network started successfully" |
| else |
| echo "Network start failed" |
| echo $CONNECT_OUT |
| fi |
| |
| # Save the new TRID |
| if [ -z "${PROXY_OPT}" ]; then |
| TRID=`echo "$CONNECT_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"` |
| if [ -n "$TRID" ]; then |
| save_state "TRID" $TRID |
| fi |
| fi |
| } |
| |
| # |
| # $ sudo mbimcli -d /dev/cdc-wdm0 --disconnect="0" |
| # [/dev/cdc-wdm0] Successfully disconnected |
| # [/dev/cdc-wdm0] Connection status: |
| # Session ID: '0' |
| # Activation state: 'deactivated' |
| # Voice call state: 'none' |
| # IP type: 'default' |
| # Context type: 'internet' |
| # Network error: 'unknown' |
| # |
| disconnect () |
| { |
| # Always close the session when disconnecting |
| if [ -n "${PROXY_OPT}" ]; then |
| EXTRA_OPT="${PROXY_OPT}" |
| elif [ -n "$TRID" ]; then |
| EXTRA_OPT="--no-open=$TRID" |
| else |
| EXTRA_OPT="" |
| fi |
| DISCONNECT_CMD="mbimcli -d $DEVICE --disconnect ${EXTRA_OPT}" |
| |
| echo "Stopping network with '$DISCONNECT_CMD'..." |
| |
| DISCONNECT_OUT=`$DISCONNECT_CMD` |
| if [ $? -eq 0 ]; then |
| echo "Network stopped successfully" |
| else |
| echo "Network stop failed" |
| echo $DISCONNECT_OUT |
| fi |
| |
| clear_state |
| } |
| |
| # |
| # $ sudo mbimcli -d /dev/cdc-wdm0 --query-connection-state --no-close |
| # [/dev/cdc-wdm0] Connection status: |
| # Session ID: '0' |
| # Activation state: 'deactivated' |
| # Voice call state: 'none' |
| # IP type: 'default' |
| # Context type: 'none' |
| # Network error: 'unknown' |
| # |
| status () |
| { |
| if [ -n "${PROXY_OPT}" ]; then |
| EXTRA_OPT="${PROXY_OPT}" |
| elif [ -n "$TRID" ]; then |
| EXTRA_OPT="--no-open=$TRID --no-close" |
| else |
| EXTRA_OPT="" |
| fi |
| |
| STATUS_CMD="mbimcli -d $DEVICE --query-connection-state ${EXTRA_OPT}" |
| echo "Getting status with '$STATUS_CMD'..." |
| |
| STATUS_OUT=`$STATUS_CMD` |
| |
| # Save the new TRID |
| if [ -z "${PROXY_OPT}" ]; then |
| TRID=`echo "$STATUS_OUT" | sed -n "s/.*TRID.*'\(.*\)'.*/\1/p"` |
| if [ -n "$TRID" ]; then |
| save_state "TRID" $TRID |
| fi |
| fi |
| |
| CONN=`echo "$STATUS_OUT" | sed -n "s/.*Activation state:.*'\(.*\)'.*/\1/p"` |
| if [ -z "$CONN" ]; then |
| echo "error: couldn't get connection status" 1>&2 |
| exit 2 |
| else |
| echo "Status: $CONN" |
| if [ "$CONN" != "connected" ]; then |
| exit 64 |
| fi |
| fi |
| } |
| |
| # Main |
| |
| # Load profile, if any |
| load_profile |
| |
| # Load previous state, if any |
| load_state |
| |
| # Process commands |
| case $COMMAND in |
| "start") |
| connect |
| ;; |
| "stop") |
| disconnect |
| ;; |
| "status") |
| status |
| ;; |
| *) |
| echo "error: unexpected command '$COMMAND'" 1>&2 |
| print_usage |
| exit 255 |
| ;; |
| esac |
| |
| exit 0 |