| #!/bin/sh |
| |
| # This program is free software; you can redistribute it and/or modify it under |
| # the terms of the GNU General Public License as published by the Free Software |
| # Foundation, either version 2 of the License, or (at your option) any later |
| # version. |
| # |
| # This program is distributed in the hope that it will be useful, but WITHOUT |
| # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| # details. |
| # |
| # You should have received a copy of the GNU General Public License along with |
| # this program; if not, write to the Free Software Foundation, Inc., 51 |
| # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| # |
| # Copyright (C) 2012-2013 Aleksander Morgado <aleksander@gnu.org> |
| |
| print_usage () |
| { |
| echo "usage: $0 [OPTIONS] [DEVICE] [COMMAND]" |
| } |
| |
| help () |
| { |
| echo "Usage: qmi-network [OPTIONS] [DEVICE] [COMMAND]" |
| echo |
| echo "Simple network management of QMI devices" |
| echo |
| echo "Commands:" |
| echo " start Start network connection" |
| echo " stop Stop network connection" |
| echo " status Query network connection status" |
| echo |
| echo "Options:" |
| echo " --help 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 qmi-network script requires a profile to be available" |
| echo " in the following path:" |
| echo " /etc/qmi-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) If you want to instruct the qmi-network script to use the" |
| echo " qmi-proxy setup, you can do so by configuring the following line" |
| echo " in the profile:" |
| echo " PROXY=yes" |
| echo |
| echo " 5) Once the qmi-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 "qmi-network @VERSION@" |
| echo "Copyright (2013-2015) 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 |
| } |
| |
| if [ $# -ne 2 ]; then |
| if [ "$1" = "--help" ]; then |
| help |
| exit 0 |
| elif [ "$1" = "--version" ]; then |
| version |
| exit 0 |
| fi |
| |
| echo "error: missing arguments" 1>&2 |
| print_usage |
| exit 255 |
| fi |
| |
| DEVICE=$1 |
| COMMAND=$2 |
| STATE_FILE=/tmp/qmi-network-state |
| PROFILE_FILE=/etc/qmi-network.conf |
| |
| load_profile () |
| { |
| if [ -f $PROFILE_FILE ]; then |
| echo "Loading profile..." |
| . $PROFILE_FILE |
| |
| if [ "x$APN" != "x" ]; then |
| echo " APN: $APN" |
| else |
| echo " APN: unset" |
| fi |
| |
| if [ "x$PROXY" = "xyes" ]; then |
| echo " qmi-proxy: $PROXY" |
| PROXY_OPT='--device-open-proxy' |
| else |
| echo " qmi-proxy: no" |
| fi |
| else |
| echo "Profile at '$PROFILE_FILE' not found..." |
| fi |
| } |
| |
| save_state () |
| { |
| KEY=$1 |
| VAL=$2 |
| |
| echo "Saving state... ($KEY: $VAL)" |
| |
| if [ -f $STATE_FILE ]; then |
| PREVIOUS=`cat $STATE_FILE` |
| PREVIOUS=`echo "$PREVIOUS" | grep -v $KEY` |
| if [ "x$PREVIOUS" != "x" ]; then |
| echo $PREVIOUS > $STATE_FILE |
| else |
| rm $STATE_FILE |
| fi |
| fi |
| |
| if [ "x$VAL" != "x" ]; then |
| echo "$KEY=\"$VAL\"" >> $STATE_FILE |
| fi |
| } |
| |
| load_state () |
| { |
| if [ -f $STATE_FILE ]; then |
| echo "Loading previous state..." |
| . $STATE_FILE |
| |
| if [ "x$CID" != "x" ]; then |
| echo " Previous CID: $CID" |
| fi |
| if [ "x$PDH" != "x" ]; then |
| echo " Previous PDH: $PDH" |
| fi |
| fi |
| } |
| |
| clear_state () |
| { |
| echo "Clearing state..." |
| rm -f $STATE_FILE |
| } |
| |
| # qmicli -d /dev/cdc-wdm0 --wds-start-network --client-no-release-cid |
| # [/dev/cdc-wdm0] Network started |
| # Packet data handle: 3634026241 |
| # [/dev/cdc-wdm0] Client ID not released: |
| # Service: 'wds' |
| # CID: '80' |
| start_network () |
| { |
| if [ "x$CID" != "x" ]; then |
| USE_PREVIOUS_CID="--client-cid=$CID" |
| fi |
| |
| if [ "x$PDH" != "x" ]; then |
| echo "error: cannot re-start network, PDH already exists" 1>&2 |
| exit 3 |
| fi |
| |
| # Read link layer protocol |
| DATA_FORMAT_CMD="qmicli -d $DEVICE --wda-get-data-format $PROXY_OPT" |
| echo "Checking data format with '$DATA_FORMAT_CMD'..." |
| if [ "x$QMIDEBUG" != "x" ]; then |
| DATA_FORMAT_OUT="\ |
| [/dev/cdc-wdm1] Successfully got data format |
| QoS flow header: no |
| Link layer protocol: '802-3' |
| Uplink data aggregation protocol: 'disabled' |
| Downlink data aggregation protocol: 'disabled' |
| NDP signature: '0' |
| Uplink data aggregation max size: '0' |
| Downlink data aggregation max size: '0'" |
| else |
| DATA_FORMAT_OUT=`$DATA_FORMAT_CMD` |
| fi |
| |
| LLP=`echo "$DATA_FORMAT_OUT" | sed -n "s/.*Link layer protocol:.*'\(.*\)'.*/\1/p"` |
| if [ "x$LLP" = "x" ]; then |
| echo "Link layer protocol not retrieved" 1>&2 |
| else |
| echo "Link layer protocol retrieved: $LLP" 1>&2 |
| if [ "x$LLP" != "x802-3" ]; then |
| DATA_FORMAT_SET_CMD="qmicli -d $DEVICE --wda-set-data-format=802-3 $PROXY_OPT" |
| echo "Updating data format with '$DATA_FORMAT_SET_CMD'..." |
| if [ "x$QMIDEBUG" != "x" ]; then |
| DATA_FORMAT_SET_OUT="\ |
| [/dev/cdc-wdm1] Successfully set data format |
| QoS flow header: no |
| Link layer protocol: '802-3' |
| Uplink data aggregation protocol: 'disabled' |
| Downlink data aggregation protocol: 'disabled' |
| NDP signature: '0' |
| Downlink data aggregation max datagrams: '0' |
| Downlink data aggregation max size: '0'" |
| else |
| DATA_FORMAT_SET_OUT=`$DATA_FORMAT_SET_CMD` |
| fi |
| |
| LLP=`echo "$DATA_FORMAT_SET_OUT" | sed -n "s/.*Link layer protocol:.*'\(.*\)'.*/\1/p"` |
| if [ "x$LLP" = "x" ]; then |
| echo "Link layer protocol not retrieved after update" 1>&2 |
| else |
| echo "New link layer protocol retrieved: $LLP" 1>&2 |
| fi |
| fi |
| fi |
| |
| START_NETWORK_CMD="qmicli -d $DEVICE --wds-start-network=$APN $USE_PREVIOUS_CID --client-no-release-cid $PROXY_OPT" |
| echo "Starting network with '$START_NETWORK_CMD'..." |
| |
| if [ "x$QMIDEBUG" != "x" ]; then |
| START_NETWORK_OUT="\ |
| [/dev/cdc-wdm0] Network started |
| Packet data handle: '3634026241' |
| [/dev/cdc-wdm0] Client ID not released: |
| Service: 'wds' |
| CID: '80'" |
| else |
| START_NETWORK_OUT=`$START_NETWORK_CMD` |
| fi |
| |
| # Save the new CID if we didn't use any before |
| if [ "x$CID" = "x" ]; then |
| CID=`echo "$START_NETWORK_OUT" | sed -n "s/.*CID.*'\(.*\)'.*/\1/p"` |
| if [ "x$CID" = "x" ]; then |
| echo "error: network start failed, client not allocated" 1>&2 |
| exit 1 |
| else |
| save_state "CID" $CID |
| fi |
| fi |
| |
| PDH=`echo "$START_NETWORK_OUT" | sed -n "s/.*handle.*'\(.*\)'.*/\1/p"` |
| if [ "x$PDH" = "x" ]; then |
| echo "error: network start failed, no packet data handle" 1>&2 |
| # Cleanup the client |
| qmicli -d "$DEVICE" --wds-noop --client-cid="$CID" $PROXY_OPT |
| clear_state |
| exit 2 |
| else |
| save_state "PDH" $PDH |
| fi |
| |
| echo "Network started successfully" |
| } |
| |
| # qmicli -d /dev/cdc-wdm0 --wds-stop-network |
| stop_network () |
| { |
| if [ "x$CID" = "x" ]; then |
| echo "Network already stopped" |
| elif [ "x$PDH" = "x" ]; then |
| echo "Network already stopped; need to cleanup CID $CID" |
| # Cleanup the client |
| qmicli -d "$DEVICE" --wds-noop --client-cid="$CID" $PROXY_OPT |
| else |
| STOP_NETWORK_CMD="qmicli -d $DEVICE --wds-stop-network=$PDH --client-cid=$CID $PROXY_OPT" |
| echo "Stopping network with '$STOP_NETWORK_CMD'..." |
| |
| if [ "x$QMIDEBUG" != "x" ]; then |
| STOP_NETWORK_OUT="\ |
| [/dev/cdc-wdm0] Network stopped |
| " |
| else |
| STOP_NETWORK_OUT=`$STOP_NETWORK_CMD` |
| fi |
| |
| echo "Network stopped successfully" |
| fi |
| |
| clear_state |
| } |
| |
| # qmicli -d /dev/cdc-wdm0 --wds-get-packet-service-status |
| packet_service_status () |
| { |
| if [ "x$CID" != "x" ]; then |
| USE_PREVIOUS_CID="--client-cid=$CID --client-no-release-cid" |
| fi |
| |
| STATUS_CMD="qmicli -d $DEVICE --wds-get-packet-service-status $USE_PREVIOUS_CID $PROXY_OPT" |
| echo "Getting status with '$STATUS_CMD'..." |
| |
| if [ "x$QMIDEBUG" != "x" ]; then |
| STATUS_OUT="\ |
| [/dev/cdc-wdm0] Connection status: 'disconnected' |
| " |
| else |
| STATUS_OUT=`$STATUS_CMD` |
| fi |
| |
| CONN=`echo "$STATUS_OUT" | sed -n "s/.*Connection status:.*'\(.*\)'.*/\1/p"` |
| if [ "x$CONN" = "x" ]; then |
| echo "error: couldn't get packet service status" 1>&2 |
| exit 2 |
| else |
| echo "Status: $CONN" |
| if [ "x$CONN" != "xconnected" ]; 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") |
| start_network |
| ;; |
| "stop") |
| stop_network |
| ;; |
| "status") |
| packet_service_status |
| ;; |
| *) |
| echo "error: unexpected command '$COMMAND'" 1>&2 |
| print_usage |
| exit 255 |
| ;; |
| esac |
| |
| exit 0 |