Implement Client configuration

- add mobile date network devices and configuration
- add client configuration via udev
- add GUI under networking tab
- add scripts to handle mobile data devices
This commit is contained in:
Christian Zeitnitz
2021-03-07 18:36:48 +01:00
parent 6d635a96d5
commit 8b0383dd20
24 changed files with 2766 additions and 114 deletions

View File

@@ -0,0 +1,4 @@
# mobile data modem - ttyUSB0 device appears
SUBSYSTEM=="tty", KERNEL=="ttyUSB0", TAG+="systemd", ENV{SYSTEMD_WANTS}="start start_ppp0_device.service"

View File

@@ -0,0 +1,3 @@
SUBSYSTEM=="net", ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="14db", NAME="hilink0", TAG+="systemd", ENV{SYSTEMD_WANTS}="start start_huawei_hilink.service"

View File

@@ -0,0 +1,106 @@
#!/bin/bash
# get info about device and signal of Huawei mobile USB devices
# parm:
# $1 : requested information (manufacturer, device, imei, imsi, telnumber, ipaddress, mode, signal, operator)
# $2 : (optional) type - hilink or modem (default: hilink)
# $3 : (optional) for hilink: ip address of the device (default: 192.168.8.1)
# for modem: tty interface for communication (default: /dev/ttypUSB2)
#
# requires: bc
# calls the scripts info_huawei_hilink.sh and info_huawei_modem.sh (same path as this script)
#
# zbchristian 2020
#
opt="device"
if [ ! -z $1 ]; then opt=${1,,}; fi
type="hilink"
if [ ! -z $2 ]; then type=${2,,}; fi
path=`dirname $0`
if [[ $type == "hilink" ]]; then
connect="192.168.8.1"
if [ ! -z $3 ]; then connect=$3; fi
script="$path/info_huawei_hilink.sh"
else
connect="/dev/ttyUSB2"
if [ ! -z $3 ]; then connect=$3; fi
script="$path/info_huawei_modem.sh"
fi
res=`$script $opt $connect`
# some results require special treatment
case $opt in
# manufacturer)
# if [[ $res == "none" ]]; then res="Huawei"; fi
# ;;
# device)
# if [[ ! $res == "none" ]]; then res="Huawei $res";
# else res="Huawei"; fi
# ;;
mode)
if [[ ! $res == "none" ]]; then
if [[ $type == "hilink" ]]; then
if [[ $res == "LTE" ]]; then res="4G"
elif [[ $res == "WCDMA" ]]; then res="3G";
else res="2G"; fi
else
if [[ $res == 7 ]]; then res="4G"
elif [[ $res < 7 ]] && [[ $res > 2 ]] ; then res="3G";
else res="2G"; fi
fi
fi
;;
signal)
# return signal strength/quality in %
if [[ $type == "hilink" ]]; then
# signal request tries to get RSRQ value
# try to get RSRQ (4G), EC/IO (3G) or RSSI (2G) value
if [[ $res == "none" ]]; then res=`$script "ecio"`; fi
if [[ ! $res == "none" ]]; then
# for rsrq and ecio assume: -3dB (100%) downto -20dB (0%)
qual=${res//dB/}
if [[ ! "$qual" =~ [-0-9\.]* ]]; then qual=-100; fi
qual=$(bc <<< "scale=0;res=$qual-0.5;res/1") # just round to next integer
if [[ $qual -le -20 ]]; then qual=0;
elif [[ $qual -ge -3 ]]; then qual=100;
else qual=$(bc <<< "scale=0;res=100.0/17.0*$qual+2000.0/17.0;res/1"); fi
else
# try rssi: >-70dBm (100%) downto -100dBm (0%)
res=`$script "rssi"`;
if [[ ! $res == "none" ]]; then
if [[ $res =~ [-0-9\.]* ]]; then res="-120 dBm"; fi
qual=${res//dBm/}
qual=$(bc <<< "scale=0;res=$qual+0.5;res/1") # just round to next integer
if [[ $qual -le -110 ]]; then qual=0;
elif [[ $qual -ge -70 ]]; then qual=100;
else qual=$(bc <<< "scale=0;res=2.5*$qual+275;res/1"); fi
fi
fi
else
# modem returns RSSI as number 0-31 - 0 = -113dB (0%), 1 = -111dB, 31 = >=51dB (100%)
qual=$(bc <<< "scale=0;res=$res*3.5+0.5;res/1")
if [[ $qual -gt 100 ]]; then res=100; fi
fi
if [[ ! "$res" == "none" ]]; then res="$res (${qual}%)"; fi
;;
operator)
# check if operator/network is just a 5 digit number -> extract network name from table
if [[ $res =~ ^[0-9]{5}$ ]]; then
mcc=${res:0:3}
mnc=${res:3:2}
op=$(cat $path/mcc-mnc-table.csv | sed -rn 's/^'$mcc'\,[0-9]*\,'$mnc'\,(.*\,){4}(.*)$/\2/p')
if [[ ! -z $op ]]; then res="$op ($res)"; fi
fi
;;
*)
;;
esac
echo $res

View File

@@ -0,0 +1,49 @@
#!/bin/bash
# Infosramtion about HUAWEI hilink (router) modem
# -----------------------------------------------
# get info about the device and signal
# parameter: $1 - see opts list below
# $2 - host ip address for API calls (optional)
# returns the value of the parameter, or "none" if not found or empty
#
# zbchristian 2020
opts=("device" "imei" "imsi" "telnumber" "ipaddress" "mode" "signal" "rssi" "rsrq" "rsrp" "sinr" "ecio" "operator")
# xml tags to extract information from
tags=("devicename" "imei" "imsi" "msisdn" "wanipaddress" "workmode" "rsrq" "rssi" "rsrq" "rsrp" "sinr" "ecio" "fullname")
iurl=( 0 0 0 0 0 0 1 1 1 1 1 1 2)
# api urls
urls=("api/device/information" "api/device/signal" "api/net/current-plmn")
host="192.168.8.1"
if [ ! -z $2 ]; then host=$2; fi
avail=`timeout 0.5 ping -c 1 $host | sed -rn 's/.*time=.*/1/p'`
if [[ -z $avail ]]; then echo "none"; exit; fi
idx=-1
opt=${opts[0]}
if [ ! -z $1 ]; then opt=$1; fi
for i in "${!opts[@]}"; do
if [[ ${opts[$i]} == $opt ]]; then idx=$i; fi
done
if [[ $idx == -1 ]];then echo "none"; exit; fi
par=${tags[$idx]}
iu=${iurl[$idx]}
url="http://$host/${urls[$iu]}"
# echo "Found option $opt at index $idx - tag $par url $url "
info=""
if [ ! -z $url ]; then info=`curl -s $url`; fi
result=`echo $info | sed -rn 's/.*<'"$par"'>(.*)<\/'"$par"'>.*/\1/pi'`
if [ -z "$result" ]; then result="none"; fi
echo $result

View File

@@ -0,0 +1,52 @@
#!/bin/bash
# Information about HUAWEI modem - via AT commands
# ------------------------------------------------
# get info about the device and signal
# parameter: $1 - see opts list below
# $2 - tty device name for the communicaton (optional)
# returns the value of the parameter, or "none" if not found or empty
#
# requires: socat
#
# zbchristian 2020
opts=("manufacturer" "device" "imei" "imsi" "telnumber" "mode" "signal" "operator")
# at command to extract information
atcmds=("AT+CGMI" "AT+CGMM" "AT+CGSN" "AT+CIMI" "AT+CNUM" "AT+COPS?" "AT+CSQ" "AT+COPS?")
# regexp pattern to extract wanted information from result string
pats=( " " " " " " " " ".*\,\"([0-9\+]*)\".*" '.*\,([0-9])$' ".*: ([0-9]*).*" '.*\,\"([^ ]*)\".*$')
# tty device for communication - usually 3 tty devices are created and the 3rd ttyUSB2 is available, even, when the device is connected
dev="/dev/ttyUSB2"
atsilent="AT^CURC=0"
if [ ! -z $2 ]; then dev=$2; fi
idx=-1
opt=${opts[0]}
if [ ! -z $1 ]; then opt=$1; fi
for i in "${!opts[@]}"; do
if [[ ${opts[$i]} == $opt ]]; then idx=$i; fi
done
if [[ $idx == -1 ]];then echo "none"; exit; fi
atcmd=${atcmds[$idx]}
pat=${pats[$idx]}
result=`(echo $atsilent; echo $atcmd) | sudo /usr/bin/socat - $dev`
# escape the AT command to be used in the regexp
atesc=${atcmd//[\+]/\\+}
atesc=${atesc//[\?]/\\?}
result=`echo $result | sed -rn 's/.*'"$atesc"'\s([^ ]+|[^ ]+ [^ ]+)\sOK.*$/\1/pg'`
if [[ $pat != " " ]]; then
result=`echo $result | sed -rn 's/'"$pat"'/\1/pg'`
fi
if [ -z "$result" ]; then result="none"; fi
echo $result

View File

@@ -0,0 +1,13 @@
# interfaces(5) file used by ifup(8) and ifdown(8)
# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d
auto ppp0
iface ppp0 inet wvdial
provider connect
pre-up /usr/local/sbin/ppp0_setpin.sh
up /usr/local/sbin/ppp0_route.sh

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,138 @@
#!/bin/bash
# connect/disconnect Huawei mobile data stick in Hilink mode (e.g. E3372h)
# ========================================================================
# - send xml formatted string via HTTP API to stick
# - Requires session and verification token, which is obtained by an API call
#
# options: -l "user":"password" - login data - DOES NOT WORK YET
# -h 192.168.8.1 - host ip address
# -p 1234 - PIN of SIM card
# -c 0/1 - connect - set datamode off/on
# required software: curl, base64
#
# TODO: implement login into API - currently the login has to be disabled!
#
# zbchristian 2020
# obtain session and verification token
function _SessToken() {
SesTok=`sudo curl -s http://$host/api/webserver/SesTokInfo -m 5 2> /dev/null`
if [ -z "$SesTok" ]; then exit; fi
token=`echo $SesTok | sed -r 's/.*<TokInfo>(.*)<\/TokInfo>.*/\1/'`
sesinfo=`echo $SesTok | sed -r 's/.*<SesInfo>(.*)<\/SesInfo>.*/\1/'`
}
function _login() {
# ----------------------- THIS DOES NOT WORK ------------------------------------------
# login to web api
_SessToken
if [[ ! -z $user ]] && [[ ! -z $pw ]]; then
# password encoding
# type 3 : base64(pw) encoded
# type 4 : base64(sha256sum(user + base64(sha256sum(pw)) + token))
pwtype3=$(echo $pw | base64 --wrap=0)
hashedpw=$(echo -n "$pw" | sha256sum -b | cut -d " " -f1 | base64 --wrap=0)
pwtype4=$(echo -n "$user$hashedpw$token" | sha256sum -b | cut -d " " -f1 | base64 --wrap=0)
apiurl="api/user/login"
xmldata="<?xml version='1.0' encoding='UTF-8'?><request><Username>$user</Username><Password>$pwtype4</Password><password_type>4</password_type></request>"
# xmldata="<?xml version='1.0' encoding='UTF-8'?><request><Username>$user</Username><Password>$pwtype3</Password><password_type>3</password_type></request>"
xtraopts="--dump-header /tmp/hilink_login_hdr.txt"
_sendRequest
# get updated session cookie
sesinfo=$(grep "SessionID=" /tmp/hilink_login_hdr.txt | cut -d ':' -f2 | cut -d ';' -f1)
token=$(grep "__RequestVerificationTokenone" /tmp/hilink_login_hdr.txt | cut -d ':' -f2)
echo "Login Cookie $sesinfo"
echo "Login Token $token"
fi
# ------------------------------ DO NOT USE THE LOGIN CODE ----------------------------------
}
function _switchMobileData() {
# switch mobile data on/off
if [[ $datamode -ge 0 ]]; then
xmldata="<?xml version: '1.0' encoding='UTF-8'?><request><dataswitch>$datamode</dataswitch></request>"
apiurl="api/dialup/mobile-dataswitch"
_sendRequest
fi
}
function _enableSIM() {
#SimState:
#255 - no SIM,
#256 - error CPIN,
#257 - ready,
#258 - PIN disabled,
#259 - check PIN,
#260 - PIN required,
#261 - PUK required
status=`curl -s http://$host/api/pin/status -m 10`
state=`echo $status | sed -rn 's/.*<simstate>(.*)<\/simstate>.*/\1/pi'`
if [[ $state -eq 257 ]]; then echo "Hilink: SIM ready"|systemd-cat; return; fi
if [[ $state -eq 260 ]]; then echo "Hilink: Set PIN"|systemd-cat; _setPIN; fi
}
function _setPIN() {
if [[ ! -z $pin ]]; then
xmldata="<?xml version: '1.0' encoding='UTF-8'?><request><OperateType>0</OperateType><CurrentPin>$pin</CurrentPin><NewPin></NewPin><PukCode></PukCode></request>"
apiurl="api/pin/operate"
_sendRequest
fi
}
function _sendRequest() {
result=""
if [[ -z $xmldata ]]; then return; fi
result=`curl -s http://$host/$apiurl -m 10 \
-H "Content-Type: application/xml" \
-H "Cookie: $sesinfo" \
-H "__RequestVerificationToken: $token" \
-d "$xmldata" $xtraopts 2> /dev/null`
xtraopts=""
}
# handle options
host="192.168.8.1"
pin=""
user=""
pw=""
datamode=-1
connect=-1
while getopts ":c:h:l:m:p:" opt; do
case $opt in
h) if [[ $OPTARG =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then host="$OPTARG"; fi
;;
p) if [[ $OPTARG =~ ^[0-9]{4,8} ]]; then pin="$OPTARG"; fi
;;
l) if [[ $OPTARG =~ ^[0-9a-zA-Z]*:.*$ ]]; then
user=$(echo "$OPTARG" | cut -d':' -f1);
pw=$(echo "$OPTARG" | cut -d':' -f2);
fi
;;
c) if [[ $OPTARG == "1" ]]; then datamode=1; else datamode=0; fi
;;
esac
done
echo "Hilink: switch device at $host to mode $datamode" | systemd-cat
# check if device is reachable
avail=`timeout 0.5 ping -c 1 $host | sed -rn 's/.*time=.*/1/p'`
if [[ -z $avail ]]; then
echo "Hilink: no link to host" | systemd-cat
exit
fi
token=""
Sesinfo=""
xmldata=""
xtraopts=""
result=""
_SessToken
_enableSIM
_switchMobileData # check and perform enable/disable mobile data connection

View File

@@ -0,0 +1,21 @@
#!/bin/bash
#
# get gateway and ip address of UTMS modem connected to ppp0
# add a default route
# called by /etc/network/interfaces.d/ppp0, when device is coming up
#
ppp0rt=""
let i=1
while [ -z "$ppp0rt" ] ; do
let i+=1
if [ $i -gt 20 ]; then
exit 1
fi
sleep 1
ppp0rt=`ip route list | grep -m 1 ppp0`
done
gate=`echo $ppp0rt | sed -rn 's/(([0-9]{1,3}\.){3}[0-9]{1,3}).*ppp0.*src (([0-9]{1,3}\.){3}[0-9]{1,3})/\1/p'`
src=`echo $ppp0rt | sed -rn 's/(([0-9]{1,3}\.){3}[0-9]{1,3}).*ppp0.*src (([0-9]{1,3}\.){3}[0-9]{1,3})/\3/p'`
ip route add default via $gate proto dhcp src $src metric 10
exit 0

View File

@@ -0,0 +1,21 @@
#!/bin/bash
# in case /dev/ttyUSB0 does not exist, wait for it at most 30 seconds
let i=1
while ! test -c /dev/ttyUSB0; do
let i+=1
if [ $i -gt 2 ]; then
logger -s -t setpin "/dev/ttyUSB0 does not exist"
exit 3
fi
logger -s -t setpin "waiting 3 seconds for /dev/ttyUSB0"
sleep 3
done
# check for pin and set it if necessary
wvdial pinstatus 2>&1 | grep -q '^+CPIN: READY'
if [ $? -eq 0 ]; then
logger -s -t setpin "SIM card is ready to use :-)"
else
logger -s -t setpin "setting PIN"
wvdial pin 2>/dev/null
fi
exit 0

View File

@@ -0,0 +1,13 @@
[Unit]
Description=Bring up HUAWEI mobile hilink device
[Service]
Type=oneshot
RemainAfterExit=no
ExecStart=/bin/sleep 15
ExecStart=/usr/local/sbin/switchClientState.sh up
[Install]
Alias=start_ltemodem.service
WantedBy=multi-user.target

View File

@@ -0,0 +1,16 @@
[Unit]
Description=Start ppp0 interface
BindsTo=dev-ttyUSB0.device
After=dev-ttyUSB0.device
[Service]
Type=forking
RemainAfterExit=yes
ExecStart=/sbin/ifup ppp0
ExecStop=/sbin/ifdown ppp0
[Install]
Alias=startppp0.service
WantedBy=multi-user.target

View File

@@ -0,0 +1,49 @@
#!/bin/bash
#
# parameters: up or down
# current client from getClients.sh
#
# requires: getClients.sh, onoff_huawei_hilink.sh in same path
# ifconfig, ifup, ifdown, systemd-cat
#
#
# zbchristian 2020
path=`dirname $0`
clients=$($path/getClients.sh simple)
if [[ -z $clients ]] || [[ $(echo $clients| grep -oP '(?<="clients": )\d') == 0 ]]; then echo "$0 : No client found"|systemd-cat; exit; fi
devs=( $(echo $clients | grep -oP '(?<="name": ")\w*(?=")') )
types=( $(echo $clients | grep -oP '(?<="type": )\d') )
# find the device with the max type number
imax=0
type=0
for i in "${!devs[@]}"; do
if [[ ${types[$i]} > $type ]]; then imax=$i; type=${types[$i]}; fi
done
device=${devs[$imax]}
echo "$0: try to set $device $1" | systemd-cat
connected=`ifconfig -a | grep -i $device -A 1 | grep -oP "(?<=inet )([0-9]{1,3}\.){3}[0-9]{1,3}"`
if [ -z "$connected" ] && [[ $1 == "up" ]]; then
if [[ $type == 3 ]]; then ip link set $device up; fi
if [[ $type == 5 ]]; then ifup $device; fi
fi
if [[ ! -z "$connected" ]] && [[ $1 == "down" ]]; then
if [[ $type == 3 ]]; then ip link set $device down; fi
if [[ $type == 5 ]]; then ifdown $device; fi
fi
if [[ $type == 4 ]]; then
ipadd=$(echo $connected | grep -oP "([0-9]{1,3}\.){2}[0-9]{1,3}")".1" # get ip address of the Hilink API
mode=0
if [[ $1 == "up" ]]; then mode=1; fi
if [[ -f /etc/raspap/networking/mobiledata.ini ]]; then
pin=$(cat /etc/raspap/networking/mobiledata.ini | sed -rn 's/pin = ([0-9]*)$/\1/p' )
fi
$path/onoff_huawei_hilink.sh -c $mode -h $ipadd -p $pin
fi

View File

@@ -0,0 +1,21 @@
[Dialer Defaults]
Modem Type = Analog Modem
ISDN = 0
Baud = 9600
Modem = /dev/ttyUSB0
[Dialer pin]
Init1 = AT+CPIN="XXXX"
[Dialer connect]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3 = AT+CGDCONT=1,"IP","web.vodafone.de"
New PPPD = yes
Phone = *99#
Password = me
Username = vodafone
Stupid Mode = 1
[Dialer pinstatus]
Init1 = AT+CPIN?