Merge pull request #16 from RaspAP/feature/zbchristian-clients

Feature/zbchristian clients
This commit is contained in:
Bill Zimmerman 2021-04-16 16:38:35 +02:00 committed by GitHub
commit 07ea4d2519
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 3217 additions and 172 deletions

View File

@ -0,0 +1,103 @@
<?php
/*
Save settings of network devices (type, name, PW, APN ...)
Called by js saveNetDeviceSettings (App/js/custom.js)
*/
require '../../includes/csrf.php';
require_once '../../includes/config.php';
require_once '../../includes/functions.php';
if (isset($_POST['interface'])) {
$int = $_POST['interface'];
$cfg = [];
$file = $int.".ini";
$cfgfile="/etc/wvdial.conf";
if ( $int == "mobiledata") {
$cfg['pin'] = $_POST["pin-mobile"];
$cfg['apn'] = $_POST["apn-mobile"];
$cfg['apn_user'] = $_POST["apn-user-mobile"];
$cfg['apn_pw'] = $_POST["apn-pw-mobile"];
if (file_exists($cfgfile)) {
if($cfg["pin"] !== "") exec('sudo /bin/sed -i "s/CPIN=\".*\"/CPIN=\"'.$cfg["pin"].'\"/gi" '.$cfgfile);
if($cfg["apn"] !== "") exec('sudo /bin/sed -i "s/\"IP\"\,\".*\"/\"IP\"\,\"'.$cfg["apn"].'\"/gi" '.$cfgfile);
if($cfg["apn_user"] !== "") exec('sudo /bin/sed -i "s/^username = .*$/Username = '.$cfg["apn_user"].'/gi" '.$cfgfile);
if($cfg["apn_pw"] !== "") exec('sudo /bin/sed -i "s/^password = .*$/Password = '.$cfg["apn_pw"].'/gi" '.$cfgfile);
}
} else if ( preg_match("/netdevices/",$int)) {
if(!isset($_POST['opts']) ) {
$jsonData = ['return'=>0,'output'=>['No valid data to add/delete udev rule ']];
echo json_encode($jsonData);
return;
} else {
$opts=explode(" ",$_POST['opts'] );
$dev=$opts[0];
$vid=$_POST["int-vid-".$dev];
$pid=$_POST["int-pid-".$dev];
$mac=$_POST["int-mac-".$dev];
$name=trim($_POST["int-name-".$dev]);
// limit device name to letters and numbers. Total length max 20
$name=preg_replace("/[^a-z0-9]/", "", strtolower($name));
$name=substr($name, 0, min(strlen($name),20));
$type=$_POST["int-type-".$dev];
$newtype=$_POST["int-new-type-".$dev];
$udevfile=$_SESSION["udevrules"]["udev_rules_file"]; // default file /etc/udev/rules.d/80-net-devices.rules";
// find the rule prototype and prefix
$rule = "";
foreach($_SESSION["udevrules"]["network_devices"] as $devt) {
if($devt["type"]==$newtype) {
$rulenew = $devt["udev_rule"];
$prefix = $devt["name_prefix"];
}
}
// check for an existing rule and delete lines with same MAC or same VID/PID
if (!empty($vid) && !empty($pid)) {
$rule = '^.*ATTRS{idVendor}==\"' . $vid . '\".*ATTRS{idProduct}==\"' . $pid . '\".*$';
exec('sudo sed -i "/'.$rule.'/Id" '.$udevfile); // clear all entries with this VID/PID
$rule = '^.*ATTRS{idProduct}==\"' . $pid . '\".*ATTRS{idVendor}==\"' . $vid . '\".*$';
exec('sudo sed -i "/'.$rule.'/Id" '.$udevfile); // clear all entries with this VID/PID
}
if (!empty($mac)) {
exec('sudo sed -i "/^.*'.$mac.'.*$/d" '.$udevfile); // clear all entries with same MAC
}
// create new entry
if ( ($type != $newtype) || !empty($name) ) { // new device type or new name
if (empty($name)) $name = $prefix."*";
if (!empty($mac)) $rule = preg_replace("/\\\$MAC\\\$/i", $mac, $rulenew);
if (!empty($vid)) $rule = preg_replace("/\\\$IDVENDOR\\\$/i", $vid, $rule);
if (!empty($pid)) $rule = preg_replace("/\\\$IDPRODUCT\\\$/i", $pid, $rule);
if (!empty($name)) $rule = preg_replace("/\\\$DEVNAME\\\$/i",$name,$rule);
if (!empty($rule)) exec('echo \''.$rule.'\' | sudo /usr/bin/tee -a '.$udevfile);
}
$jsonData = ['return'=>0,'output'=>['Settings changed for device '.$dev. '<br>Changes will only be in effect after reconnecting the device' ] ];
echo json_encode($jsonData);
return;
}
} else {
$ip = $_POST[$int.'-ipaddress'];
$netmask = mask2cidr($_POST[$int.'-netmask']);
$dns1 = $_POST[$int.'-dnssvr'];
$dns2 = $_POST[$int.'-dnssvralt'];
$cfg['interface'] = $int;
$cfg['routers'] = $_POST[$int.'-gateway'];
$cfg['ip_address'] = $ip."/".$netmask;
$cfg['domain_name_server'] = $dns1." ".$dns2;
$cfg['static'] = $_POST[$int.'-static'];
$cfg['failover'] = $_POST[$int.'-failover'];
}
if (write_php_ini($cfg, RASPI_CONFIG.'/networking/'.$file)) {
$jsonData = ['return'=>0,'output'=>['Successfully Updated Network Configuration']];
} else {
$jsonData = ['return'=>1,'output'=>['Error saving network configuration to file']];
}
} else {
$jsonData = ['return'=>2,'output'=>'Unable to detect interface'];
}
echo json_encode($jsonData);

View File

@ -16,14 +16,6 @@ $hostapd = parse_ini_file(RASPI_HOSTAPD_CONFIG, false, INI_SCANNER_RAW);
$type = "WPA";
$password = isset($hostapd['wpa_psk']) ? $hostapd['wpa_psk'] : $hostapd['wpa_passphrase'];
// use wep if configured
$wep_default_key = intval($hostapd['wep_default_key']);
$wep_key = 'wep_key' . $wep_default_key;
if (array_key_exists($wep_key, $hostapd)) {
$type = "WEP";
$password = $hostapd[$wep_key];
}
// if password is still empty, assume nopass
if (empty($password)) {
$type = "nopass";
@ -47,7 +39,8 @@ $content_length = strlen($svg);
header("Content-Type: image/svg+xml");
header("Content-Length: $content_length");
header("Last-Modified: $last_modified");
header("Content-Disposition: attachment; filename=\"qr.svg\"");
header("ETag: \"$etag\"");
header("X-QR-Code-Content: $data");
echo shell_exec($command);
echo $svg;

View File

@ -130,7 +130,8 @@ function setupBtns() {
$('#btnSummaryRefresh').click(function(){getAllInterfaces();});
$('.intsave').click(function(){
var int = $(this).data('int');
saveNetworkSettings(int);
var opts = $(this).data('opts');
saveNetDeviceSettings(int,opts);
});
$('.intapply').click(function(){
applyNetworkSettings();
@ -173,6 +174,24 @@ function loadWifiStations(refresh) {
}
$(".js-reload-wifi-stations").on("click", loadWifiStations(true));
function saveNetDeviceSettings(int,opts="") {
var frmInt = $('#frm-'+int).find(':input');
var arrFormData = {};
$.each(frmInt,function(i3,v3){
if($(v3).attr('type') == 'radio') {
arrFormData[$(v3).attr('id')] = $(v3).prop('checked');
} else {
arrFormData[$(v3).attr('id')] = $(v3).val();
}
});
arrFormData['interface'] = int;
arrFormData['opts'] = opts;
$.post('ajax/networking/save_net_dev_config.php',arrFormData,function(data){
var jsonData = JSON.parse(data);
$('#msgNetworking').html(msgShow(jsonData['return'],jsonData['output']));
});
}
/*
Populates the DHCP server form fields
Option toggles are set dynamically depending on the loaded configuration

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,34 @@
#!/bin/bash
# start with "sudo"
# parameters: up or on
#
# switch client state to UP
# the actual code is in PHP
# get webroot
webroot=$(cat /etc/lighttpd/lighttpd.conf | sed -rn 's/server.document-root\s*=\s*\"(.*)\"\s*$/\1/p')
if [ -z "$webroot" ] || [ ! -d "$webroot" ]; then
exit
fi
cd $webroot
state=""
if [ ! -z $1 ] && [[ $1 =~ ^(up|on|UP|ON)$ ]]; then
state="up"
elif [ ! -z $1 ] && [[ $1 =~ ^(down|off|DOWN|OFF)$ ]]; then
state="down"
fi
[ -z "$state" ] && exit
php << _EOF_
<?php
require_once("includes/config.php");
require_once("includes/get_clients.php");
loadClientConfig();
setClientState("$state");
?>
_EOF_

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?

View File

@ -0,0 +1,64 @@
{
"info": "UDEV rules for different client types. $...$ expressions will be replaces automatically ($MAC$, $IDVENDOR$, $IDPRODUCT$, $DEVNAME$)",
"udev_rules_file": "/etc/udev/rules.d/80-raspap-net-devices.rules",
"script_path": "/usr/local/sbin",
"network_devices": [
{
"type": "eth",
"type_info": "ethernet port",
"clientid": 0,
"comment": "standard ethernet port",
"name_prefix": "eth",
"udev_rule": "SUBSYSTEM==\"net\", ACTION==\"add\", ATTR{address}==\"$MAC$\", NAME=\"$DEVNAME$\", ENV{raspapType}=\"eth\" "
},
{
"type": "usb",
"type_info": "usb network interface",
"clientid": 1,
"comment": "network interface - e.g. USB tethering of an Android phone ",
"name_prefix": "usb",
"udev_rule": "SUBSYSTEM==\"net\", ACTION==\"add\", SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"$IDVENDOR$\", ATTRS{idProduct}==\"$IDPRODUCT$\", NAME=\"$DEVNAME$\", ENV{raspapType}=\"eth\" "
},
{
"type": "wlan",
"type_info": "wireless adapter",
"clientid": 2,
"comment": "standard wireless interface",
"name_prefix": "wlan",
"udev_rule": "SUBSYSTEM==\"net\", ACTION==\"add\", ATTR{address}==\"$MAC$\", NAME=\"$DEVNAME$\", ENV{raspapType}=\"wlan\" "
},
{
"type": "ppp",
"type_info": "mobile data modem",
"clientid": 3,
"name_prefix": "ppp",
"comment": "recognized mobile data modems are automatically named as ppp0-9. Renaming is not possible. Dialin service relies on the name",
"udev_rule": "SUBSYSTEM==\"tty\", KERNEL==\"ttyUSB0\", TAG+=\"systemd\", ENV{SYSTEMD_WANTS}=\"start start_ppp0_device.service\" "
},
{
"type": "hilink",
"type_info": "Huawei Hilink",
"clientid": 4,
"comment": "Huawei mobile data device in router mode. Control via HTTP",
"name_prefix": "hilink",
"default_ip": "192.168.8.1",
"udev_rule": "SUBSYSTEM==\"net\", ACTION==\"add\", SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"$IDVENDOR$\", ATTRS{idProduct}==\"$IDPRODUCT$\", NAME=\"$DEVNAME$\", ENV{raspapType}=\"hilink\", TAG+=\"systemd\", ENV{SYSTEMD_WANTS}=\"start start_huawei_hilink.service\" "
},
{
"type": "phone",
"type_info": "USB tethered phone",
"clientid": 5,
"comment": "ethernet access provided by tethering from phone via USB",
"name_prefix": "phone",
"udev_rule": "SUBSYSTEM==\"net\", ACTION==\"add\", SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"$IDVENDOR$\", ATTRS{idProduct}==\"$IDPRODUCT$\", NAME=\"$DEVNAME$\", ENV{raspapType}=\"phone\" "
},
{
"type": "tun",
"type_info": "tunnel device",
"clientid": -1,
"comment": "tunneling device used by OpenVPN",
"name_prefix": "tun"
}
]
}

View File

@ -27,6 +27,8 @@ define('RASPI_TORPROXY_CONFIG', '/etc/tor/torrc');
define('RASPI_LIGHTTPD_CONFIG', '/etc/lighttpd/lighttpd.conf');
define('RASPI_ACCESS_CHECK_IP', '1.1.1.1');
define('RASPI_ACCESS_CHECK_DNS', 'one.one.one.one');
define('RASPI_CLIENT_CONFIG_PATH', '/etc/raspap/networking/client_udev_prototypes.json');
define('RASPI_CLIENT_SCRIPT_PATH', '/usr/local/sbin');
// Constant for the 5GHz wireless regulatory domain
define('RASPI_5GHZ_ISO_ALPHA2', array('NL','US'));

View File

@ -3,6 +3,7 @@
require_once 'includes/config.php';
require_once 'includes/wifi_functions.php';
require_once 'includes/functions.php';
require_once 'includes/get_clients.php';
/**
* Show dashboard page.
@ -23,6 +24,27 @@ function DisplayDashboard(&$extraFooterScripts)
$status->showMessages();
return;
}
// ------------------------- Button pressed to switch client on/off ---------------------------------------------------------
$switchedOn = false;
if (!RASPI_MONITOR_ENABLED) {
if (isset($_POST['ifdown_wlan0'])) {
// Pressed stop button
$status->addMessage(sprintf(_('Interface is going %s.'), _('down')), 'warning');
setClientState("down");
$status->addMessage(sprintf(_('Interface is now %s.'), _('down')), 'success');
} elseif (isset($_POST['ifup_wlan0'])) {
// Pressed start button
$status->addMessage(sprintf(_('Interface is going %s.'), _('up')), 'warning');
setClientState("up");
$status->addMessage(sprintf(_('Interface is now %s.'), _('up')), 'success');
$switchedOn = true;
}
}
// ----------------------------- INFOS ABOUT THE ACCESS POINT -------------------------------------------------------------
exec('ip a show '.$_SESSION['ap_interface'], $stdoutIp);
$stdoutIpAllLinesGlued = implode(" ", $stdoutIp);
$stdoutIpWRepeatedSpaces = preg_replace('/\s\s+/', ' ', $stdoutIpAllLinesGlued);
@ -88,103 +110,40 @@ function DisplayDashboard(&$extraFooterScripts)
$strTxBytes .= getHumanReadableDatasize($strTxBytes);
}
define('SSIDMAXLEN', 32);
// Warning iw comes with: "Do NOT screenscrape this tool, we don't consider its output stable."
exec('iw dev ' .$_SESSION['wifi_client_interface']. ' link ', $stdoutIw);
$stdoutIwAllLinesGlued = implode('+', $stdoutIw); // Break lines with character illegal in SSID and MAC addr
$stdoutIwWRepSpaces = preg_replace('/\s\s+/', ' ', $stdoutIwAllLinesGlued);
preg_match('/Connected to (([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2}))/', $stdoutIwWRepSpaces, $matchesBSSID) || $matchesBSSID[1] = '';
$connectedBSSID = $matchesBSSID[1];
$connectedBSSID = empty($connectedBSSID) ? "-" : $connectedBSSID;
$wlanHasLink = false;
if ($interfaceState === 'UP') {
$wlanHasLink = true;
// ------------------------ INFOS ABOUT THE CLIENT---------------------------------------------------------------
$clientinfo=array("name"=>"none","type"=>-1,"connected"=>"n");
$raspi_client=$_SESSION['wifi_client_interface'];
loadClientConfig();
$all_clients = getClients(false);
$clientinfo = array("name" => "none", "connected" => "n");
if ( ($idx = findCurrentClientIndex($all_clients)) >= 0) $clientinfo = $all_clients["device"][$idx];
if ($clientinfo["name"] != "none") $raspi_client = $clientinfo["name"];
$interfaceState = $clientinfo["connected"] == "y" ? 'UP' : 'DOWN';
$txPower="";
if ($clientinfo["type"] == "wlan") {
// txpower is now displayed on iw dev(..) info command, not on link command.
exec('iw dev '.$clientinfo["name"].' info | sed -rn "s/.*txpower ([0-9]*)[0-9\.]*( dBm).*/\1\2/p"', $stdoutIwInfo);
if (!empty($stdoutIwInfo)) $txPower=$stdoutIwInfo[0];
}
if (!preg_match('/SSID: ([^+]{1,'.SSIDMAXLEN.'})/', $stdoutIwWRepSpaces, $matchesSSID)) {
$wlanHasLink = false;
$matchesSSID[1] = 'None';
}
$connectedSSID = $matchesSSID[1];
preg_match('/freq: (\d+)/i', $stdoutIwWRepSpaces, $matchesFrequency) || $matchesFrequency[1] = '';
$frequency = $matchesFrequency[1].' MHz';
preg_match('/signal: (-?[0-9]+ dBm)/i', $stdoutIwWRepSpaces, $matchesSignal) || $matchesSignal[1] = '';
$signalLevel = $matchesSignal[1];
$signalLevel = empty($signalLevel) ? "-" : $signalLevel;
preg_match('/tx bitrate: ([0-9\.]+ [KMGT]?Bit\/s)/', $stdoutIwWRepSpaces, $matchesBitrate) || $matchesBitrate[1] = '';
$bitrate = $matchesBitrate[1];
$bitrate = empty($bitrate) ? "-" : $bitrate;
// txpower is now displayed on iw dev(..) info command, not on link command.
exec('iw dev '.$_SESSION['wifi_client_interface'].' info ', $stdoutIwInfo);
$stdoutIwInfoAllLinesGlued = implode(' ', $stdoutIwInfo);
$stdoutIpInfoWRepSpaces = preg_replace('/\s\s+/', ' ', $stdoutIwInfoAllLinesGlued);
preg_match('/txpower ([0-9\.]+ dBm)/i', $stdoutIpInfoWRepSpaces, $matchesTxPower) || $matchesTxPower[1] = '';
$txPower = $matchesTxPower[1];
// iw does not have the "Link Quality". This is a is an aggregate value,
// and depends on the driver and hardware.
// Display link quality as signal quality for now.
$strLinkQuality = 0;
if ($signalLevel > -100 && $wlanHasLink) {
if ($signalLevel >= 0) {
$strLinkQuality = 100;
} else {
$strLinkQuality = 100 + intval($signalLevel);
}
}
$wlan0up = false;
$classMsgDevicestatus = 'warning';
if ($interfaceState === 'UP') {
$wlan0up = true;
$classMsgDevicestatus = 'success';
}
if (!RASPI_MONITOR_ENABLED) {
if (isset($_POST['ifdown_wlan0'])) {
// Pressed stop button
if ($interfaceState === 'UP') {
$status->addMessage(sprintf(_('Interface is going %s.'), _('down')), 'warning');
exec('sudo ip link set '.$_SESSION['wifi_client_interface'].' down');
$wlan0up = false;
$status->addMessage(sprintf(_('Interface is now %s.'), _('down')), 'success');
} elseif ($interfaceState === 'unknown') {
$status->addMessage(_('Interface state unknown.'), 'danger');
} else {
$status->addMessage(sprintf(_('Interface already %s.'), _('down')), 'warning');
}
} elseif (isset($_POST['ifup_wlan0'])) {
// Pressed start button
if ($interfaceState === 'DOWN') {
$status->addMessage(sprintf(_('Interface is going %s.'), _('up')), 'warning');
exec('sudo ip link set ' .$_SESSION['wifi_client_interface']. ' up');
exec('sudo ip -s a f label ' . $_SESSION['wifi_client_interface']);
$wlan0up = true;
$status->addMessage(sprintf(_('Interface is now %s.'), _('up')), 'success');
} elseif ($interfaceState === 'unknown') {
$status->addMessage(_('Interface state unknown.'), 'danger');
} else {
$status->addMessage(sprintf(_('Interface already %s.'), _('up')), 'warning');
}
} else {
$status->addMessage(sprintf(_('Interface is %s.'), strtolower($interfaceState)), $classMsgDevicestatus);
}
}
if ($switchedOn) exec('sudo ip -s a f label ' . $raspi_client);
// brought in from template
$arrHostapdConf = parse_ini_file(RASPI_CONFIG.'/hostapd.ini');
$bridgedEnable = $arrHostapdConf['BridgedEnable'];
$clientInterface = $_SESSION['wifi_client_interface'];
if ($arrHostapdConf['WifiAPEnable'] == 1) {
$client_interface = 'uap0';
} else {
$client_interface = $clientinfo["name"];
}
$apInterface = $_SESSION['ap_interface'];
$clientInterface = $raspi_client;
$MACPattern = '"([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}"';
if (getBridgedState()) {
$moreLink = "hostapd_conf";
exec('iw dev ' . $apInterface . ' station dump | grep -oE ' . $MACPattern, $clients);
@ -192,11 +151,39 @@ function DisplayDashboard(&$extraFooterScripts)
$moreLink = "dhcpd_conf";
exec('cat ' . RASPI_DNSMASQ_LEASES . '| grep -E $(iw dev ' . $apInterface . ' station dump | grep -oE ' . $MACPattern . ' | paste -sd "|")', $clients);
}
$ifaceStatus = $wlan0up ? "up" : "down";
$ifaceStatus = $clientinfo["connected"]=="y" ? "up" : "down";
$isClientConfigured = true;
switch($clientinfo["type"]) {
case "eth":
case "usb":
$client_title = "Client: Ethernet cable";
$type_name = "Ethernet";
break;
case "phone":
$client_title = "Client: Smartphone (USB tethering)";
$type_name = "Smartphone";
break;
case "wlan":
$client_title = "Wireless Client";
$type_name = "Wifi";
break;
case "ppp":
case "hilink":
$client_title = "Mobile Data Client";
$type_name = "Mobile Data";
break;
default:
$client_title = "No information available";
$type_name = "Not configured";
$ifaceStatus = "warn";
$isClientConfigured = false;
}
echo renderTemplate(
"dashboard", compact(
"clients",
"client_title",
"type_name",
"moreLink",
"apInterface",
"clientInterface",
@ -211,14 +198,9 @@ function DisplayDashboard(&$extraFooterScripts)
"strRxBytes",
"strTxPackets",
"strTxBytes",
"connectedSSID",
"connectedBSSID",
"bitrate",
"signalLevel",
"txPower",
"frequency",
"strLinkQuality",
"wlan0up"
"clientinfo",
"isClientConfigured"
)
);
$extraFooterScripts[] = array('src'=>'app/js/dashboardchart.js', 'defer'=>false);

View File

@ -755,6 +755,17 @@ function getNightmode(){
} else {
return false;
}
}
// search array for matching string and return only first matching group
function preg_only_match($pat,$haystack) {
$match = "";
if(!empty($haystack) && !empty($pat)) {
if(!is_array($haystack)) $haystack = array($haystack);
$str = preg_grep($pat,$haystack);
if (!empty($str) && preg_match($pat,array_shift($str),$match) === 1 ) $match = $match[1];
}
return $match;
}
// Sanitizes a string for QR encoding
@ -763,5 +774,4 @@ function getNightmode(){
function qr_encode($str)
{
return preg_replace('/(?<!\\\)([\":;,])/', '\\\\\1', $str);
}
}

296
includes/get_clients.php Normal file
View File

@ -0,0 +1,296 @@
<?php
require_once 'includes/functions.php';
function getClients($simple=true)
{
exec('ifconfig -a | grep -oP "^(?!lo)(\w*)"', $rawdevs); // all devices except loopback
$path=RASPI_CLIENT_SCRIPT_PATH;
$cl=array();
if (!empty($rawdevs) && is_array($rawdevs)) {
$cl["clients"]=count($rawdevs);
// search for possibly not connected modem
exec("find /sys/bus/usb/devices/usb*/ -name dev ", $devtty); // search for ttyUSB
$devtty = preg_only_match("/(ttyUSB0)/", $devtty);
if (empty(preg_only_match("/(ppp)[0-9]/", $rawdevs))) {
if (!empty($devtty)) {
$rawdevs[]="ppp0";
exec("udevadm info --name='$devtty' 2> /dev/null");
}
}
foreach ($rawdevs as $i => $dev) {
$cl["device"][$i]["name"]=$dev;
$nam = (preg_match("/^(\w+)[0-9]$/",$dev,$nam) === 1) ? $nam=$nam[1] : "";
$cl["device"][$i]["type"]=$ty=getClientType($dev);
unset($udevinfo);
exec("udevadm info /sys/class/net/$dev 2> /dev/null", $udevinfo);
if ($nam == "ppp" && isset($devtty)) {
exec("udevadm info --name='$devtty' 2> /dev/null", $udevinfo);
}
if (!empty($udevinfo) && is_array($udevinfo)) {
$model = preg_only_match("/ID_MODEL_ENC=(.*)$/", $udevinfo);
if (empty($model) || preg_match("/^[0-9a-f]{4}$/", $model) === 1) {
$model = preg_only_match("/ID_MODEL_FROM_DATABASE=(.*)$/", $udevinfo);
}
if (empty($model)) {
$model = preg_only_match("/ID_OUI_FROM_DATABASE=(.*)$/", $udevinfo);
}
$vendor = preg_only_match("/ID_VENDOR_ENC=(.*)$/", $udevinfo);
if (empty($vendor) || preg_match("/^[0-9a-f]{4}$/", $vendor) === 1) {
$vendor = preg_only_match("/ID_VENDOR_FROM_DATABASE=(.*)$/", $udevinfo);
}
$driver = preg_only_match("/ID_NET_DRIVER=(.*)$/", $udevinfo);
$vendorid = preg_only_match("/ID_VENDOR_ID=(.*)$/", $udevinfo);
$productid = preg_only_match("/ID_MODEL_ID=(.*)$/", $udevinfo);
}
$cl["device"][$i]["model"] = preg_replace("/\\\\x20/", " ", $model);
$cl["device"][$i]["vendor"] = preg_replace("/\\\\x20/", " ", $vendor);
$cl["device"][$i]["vid"] = $vendorid;
$cl["device"][$i]["pid"] = $productid;
unset($mac);
exec("cat /sys/class/net/$dev/address 2> /dev/null", $mac);
$cl["device"][$i]["mac"] = empty($mac) ? "":$mac[0];
unset($ip);
exec("ifconfig $dev 2> /dev/null", $ip);
$cl["device"][$i]["ipaddress"] = preg_only_match("/.*inet ([0-9\.]+) .*/", $ip);
switch($ty) {
case "eth":
unset($res);
exec("ip link show $dev 2> /dev/null | grep -oP ' UP '", $res);
if (empty($res) && empty($ipadd)) {
$cl["device"][$i]["connected"] = "n";
} else {
$cl["device"][$i]["connected"] = "y";
}
break;
case "wlan":
unset($retiw);
exec("iwconfig $dev 2> /dev/null | sed -rn 's/.*(mode:master).*/1/ip'", $retiw);
$cl["device"][$i]["isAP"] = !empty($retiw);
unset($retiw);
exec("iw dev $dev link 2> /dev/null", $retiw);
if (!$simple && !empty($ssid=preg_only_match("/.*SSID: ([\w ]*).*/", $retiw)) ) {
$cl["device"][$i]["connected"] = "y";
$cl["device"][$i]["ssid"] = $ssid;
$cl["device"][$i]["ap-mac"] = preg_only_match("/^Connected to ([0-9a-f\:]*).*$/", $retiw);
$sig = preg_only_match("/.*signal: (.*)$/", $retiw);
$val = preg_only_match("/^([0-9\.-]*).*$/", $sig);
if (!is_numeric($val)) {
$val = -100;
}
if ($val >= -50 ) {
$qual=100;
} else if ($val < -100) {
$qual=0;
} else {
$qual=round($val*2+200);
}
$cl["device"][$i]["signal"] = "$sig (".$qual."%)";
$cl["device"][$i]["bitrate"] = preg_only_match("/.*bitrate: ([0-9\.]* \w*\/s).*$/", $retiw);
$cl["device"][$i]["freq"] = preg_only_match("/.*freq: (.*)$/", $retiw);
$cl["device"][$i]["ap-mac"] = preg_only_match("/^Connected to ([0-9a-f\:]*).*$/", $retiw);
} else {
$cl["device"][$i]["connected"] = "n";
}
break;
case "ppp":
unset($res);
exec("ip link show $dev 2> /dev/null | grep -oP '( UP | UNKNOWN)'", $res);
if ($simple) {
if (empty($res)) {
$cl["device"][$i]["connected"] = "n";
$cl["device"][$i]["signal"] = "-100 dB (0%)";
} else {
$cl["device"][$i]["connected"] = "y";
$cl["device"][$i]["signal"] = "-0 dB (0%)";
}
break;
}
if (empty($res) && empty($ipadd)) {
$cl["device"][$i]["connected"] = "n";
} else {
$cl["device"][$i]["connected"] = "y";
}
unset($res);
exec("$path/info_huawei.sh mode modem", $res);
$cl["device"][$i]["mode"] = $res[0];
unset($res);
exec("$path/info_huawei.sh device modem", $res);
if ($res[0] != "none" ) {
$cl["device"][$i]["model"] = $res[0];
}
unset($res);
exec("$path/info_huawei.sh signal modem", $res);
$cl["device"][$i]["signal"] = $res[0];
unset($res);
exec("$path/info_huawei.sh operator modem", $res);
$cl["device"][$i]["operator"] = $res[0];
break;
case "hilink":
unset($res);
// exec("ip link show $dev 2> /dev/null | grep -oP ' UP '",$res);
exec("ifconfig -a | grep -i $dev -A 1 | grep -oP '(?<=inet )([0-9]{1,3}\.){3}'", $apiadd);
$apiadd = !empty($apiadd) ? $apiadd[0]."1" : "";
unset($res);
exec("$path/info_huawei.sh mode hilink $apiadd", $res);
$cl["device"][$i]["mode"] = $res[0];
unset($res);
exec("$path/info_huawei.sh device hilink $apiadd", $res);
if ($res[0] != "none" ) {
$cl["device"][$i]["model"] = $res[0];
}
unset($res);
exec("$path/info_huawei.sh signal hilink $apiadd", $res);
$cl["device"][$i]["signal"] = $res[0];
unset($ipadd);
exec("$path/info_huawei.sh ipaddress hilink $apiadd", $ipadd);
if (!empty($ipadd) && $ipadd[0] !== "none" ) {
$cl["device"][$i]["connected"] = "y";
$cl["device"][$i]["wan_ip"] = $ipadd[0];
} else {
$cl["device"][$i]["connected"] = "n";
$cl["device"][$i]["wan_ip"] = "-";
}
unset($res);
exec("$path/info_huawei.sh operator hilink $apiadd", $res);
$cl["device"][$i]["operator"] = $res[0];
break;
case "phone":
case "usb":
$cl["device"][$i]["connected"] = "y";
break;
default:
}
if (!isset($cl["device"][$i]["signal"])) {
$cl["device"][$i]["signal"]= $cl["device"][$i]["connected"] == "n" ? "-100 dB (0%)": "0 dB (100%)";;
}
if (!isset($cl["device"][$i]["isAP"])) {
$cl["device"][$i]["isAP"]=false;
}
}
}
return $cl;
}
function getClientType($dev) {
loadClientConfig();
// check if device type stored in DEVTYPE or raspapType (from UDEV rule) protperty of the device
exec("udevadm info /sys/class/net/$dev 2> /dev/null", $udevadm);
$type="none";
if (!empty($udevadm)) {
$type=preg_only_match("/raspapType=(\w*)/i",$udevadm);
if (empty($type)) {
$type=preg_only_match("/DEVTYPE=(\w*)/i",$udevadm);
}
}
if (empty($type) || array_search($type, $_SESSION["net-device-name-prefix"]) === false) {
// no device type yet -> get device type from device name
if (preg_match("/^(\w+)[0-9]$/",$dev,$nam) === 1) $nam=$nam[1];
else $nam="none";
if (($n = array_search($nam, $_SESSION["net-device-name-prefix"])) === false) $n = count($_SESSION["net-device-types"])-1;
$type = $_SESSION["net-device-types"][$n];
}
return $type;
}
function loadClientConfig()
{
// load network device config file for UDEV rules into $_SESSION
if (!isset($_SESSION["udevrules"])) {
$_SESSION["net-device-types"]=array();
$_SESSION["net-device-name-prefix"]=array();
try {
$udevrules = file_get_contents(RASPI_CLIENT_CONFIG_PATH);
$_SESSION["udevrules"] = json_decode($udevrules, true);
// get device types
foreach ($_SESSION["udevrules"]["network_devices"] as $dev) {
$_SESSION["net-device-name-prefix"][]=$dev["name_prefix"];
$_SESSION["net-device-types"][]=$dev["type"];
$_SESSION["net-device-types-info"][]=$dev["type_info"];
}
} catch (Exception $e) {
$_SESSION["udevrules"]= null;
}
$_SESSION["net-device-types"][]="none";
$_SESSION["net-device-types-info"][]="unknown";
$_SESSION["net-device-name-prefix"][]="none";
}
}
function findCurrentClientIndex($clients)
{
$devid = -1;
if (!empty($clients)) {
$ncl=$clients["clients"];
if ($ncl > 0) {
$ty=-1;
foreach ($clients["device"] as $i => $dev) {
$id=array_search($dev["type"], $_SESSION["net-device-types"]);
if ($id >=0 && $_SESSION["udevrules"]["network_devices"][$id]["clientid"] > $ty && !$dev["isAP"]) {
$ty=$id;
$devid=$i;
}
}
}
}
return $devid;
}
function waitClientConnected($dev, $timeout=10)
{
do {
exec('ifconfig -a | grep -i '.$dev.' -A 1 | grep -oP "(?<=inet )([0-9]{1,3}\.){3}[0-9]{1,3}"', $res);
$connected= !empty($res);
if (!$connected) {
sleep(1);
}
} while (!$connected && --$timeout > 0);
return $connected;
}
function setClientState($state)
{
$clients=getClients();
if (($idx = findCurrentClientIndex($clients)) >= 0) {
$dev = $clients["device"][$idx];
exec('ifconfig -a | grep -i '.$dev["name"].' -A 1 | grep -oP "(?<=inet )([0-9]{1,3}\.){3}[0-9]{1,3}"', $res);
if (!empty($res)) {
$connected=$res[0];
}
switch($dev["type"]) {
case "wlan":
if ($state =="up") {
exec('sudo ip link set '.$dev["name"].' up');
}
if (!empty($connected) && $state =="down") {
exec('sudo ip link set '.$dev["name"].' down');
}
break;
case "hilink":
preg_match("/^([0-9]{1,3}\.){3}/", $connected, $ipadd);
$ipadd = $ipadd[0].'1'; // ip address of the Hilink api
$mode = ($state == "up") ? 1 : 0;
$pin="";
if (file_exists(($f = RASPI_CONFIG."/networking/mobiledata.ini"))) {
$dat = parse_ini_file($f);
$pin = (isset($dat["pin"]) && preg_match("/^[0-9]*$/", $dat["pin"])) ? $dat["pin"] : "";
}
exec('sudo '.RASPI_CLIENT_SCRIPT_PATH.'/onoff_huawei_hilink.sh -c '.$mode.' -h '.$ipadd.' -p '.$pin);
break;
case "ppp":
if ($state == "up") {
exec('sudo ifup '.$dev["name"]);
}
if (!empty($connected) && $state == "down") {
exec('sudo ifdown '.$dev["name"]);
}
break;
default:
break;
}
if ($state=="up") {
waitClientConnected($dev["name"], 15);
}
}
}

View File

@ -11,10 +11,23 @@ function getRouteInfo($checkAccess)
$rInfo = array();
// get all default routes
exec('ip route list | sed -rn "s/default via (([0-9]{1,3}\.){3}[0-9]{1,3}).*dev (\w*).*src (([0-9]{1,3}\.){3}[0-9]{1,3}).*/\3 \4 \1/p"', $routes);
exec('ip route list | sed -rn "s/default dev (\w*) scope link/\1/p"', $devs);
$devpat = array("tun", "ppp"); // routing in case of VPN and PPP connection are different
foreach ($devpat as $pat) {
exec('ip route list | grep -oP "'.$pat.'[0-9]" | sort -u', $devs);
}
if (!empty($devs)) {
foreach ($devs as $dev)
exec('ip route list | sed -rn "s/(([0-9]{1,3}\.){3}[0-9]{1,3}).*dev.*("' . $dev . '").*scope link src (([0-9]{1,3}\.){3}[0-9]{1,3}).*/\3 \4 \1/p"', $routes);
foreach ($devs as $dev) {
unset($gateway);
unset($ipadd);
exec('ip route list | sed -rn "s/^.*via (([0-9]{1,3}\.){3}[0-9]{1,3}) dev "' . $dev . '".*$/\1/p" | head -n 1', $gateway);
if (empty($gateway)) {
exec('ip route list | sed -rn "s/(([0-9]{1,3}\.){3}[0-9]{1,3}).*dev.*"' . $dev . '".*scope link src.*/\1/p"', $gateway);
}
exec('ifconfig -a | grep -i ' . $dev . ' -A 1 | grep -oP "(?<=inet )([0-9]{1,3}\.){3}[0-9]{1,3}"', $ipadd);
if (!empty($gateway) && !empty($ipadd)) {
$routes[]="$dev $ipadd[0] $gateway[0]";
}
}
}
if (!empty($routes)) {
foreach ($routes as $i => $route) {
@ -41,5 +54,4 @@ function getRouteInfo($checkAccess)
}
return $rInfo;
}
?>

View File

@ -2,6 +2,8 @@
require_once 'includes/status_messages.php';
require_once 'includes/internetRoute.php';
require_once 'includes/functions.php';
require_once 'includes/get_clients.php';
/**
*
@ -17,10 +19,18 @@ function DisplayNetworkingConfig()
$arrHostapdConf = parse_ini_file(RASPI_CONFIG.'/hostapd.ini');
$bridgedEnabled = $arrHostapdConf['BridgedEnable'];
foreach ($interfaces as $interface) {
exec("ip a show $interface", $$interface);
}
loadClientConfig();
$clients=getClients();
echo renderTemplate("networking", compact(
"status",
"interfaces",
"routeInfo",
"bridgedEnabled")
"bridgedEnabled",
"clients")
);
}
?>

View File

@ -157,3 +157,4 @@ function getWifiInterface()
}
}
?>

View File

@ -56,11 +56,30 @@ function _install_raspap() {
_configure_networking
_prompt_install_adblock
_prompt_install_openvpn
_install_mobile_clients
_prompt_install_wireguard
_patch_system_files
_install_complete
}
# search for optional installation files names install_feature_*.sh
function _install_mobile_clients() {
if [ "$insiders" == 1 ]; then
echo -n "Installing support for mobile data clients"
for feature in $(ls $webroot_dir/installers/install_feature_*.sh) ; do
source $feature
f=$(basename $feature)
func="_${f%.*}"
if declare -f -F $func > /dev/null; then
_install_log "Installing $func"
$func || _install_status 1 "Not able to install feature ($func)"
else
_install_status 1 "Install file $f is missing install function $func"
fi
done
fi
}
# Prompts user to set installation options
function _config_installation() {
if [ "$upgrade" == 1 ]; then
@ -177,6 +196,9 @@ function _create_raspap_directories() {
# Create a directory to store networking configs
echo "Creating $raspap_dir/networking"
sudo mkdir -p "$raspap_dir/networking"
# Copy existing dhcpcd.conf to use as base config
echo "Adding /etc/dhcpcd.conf as base configuration"
cat /etc/dhcpcd.conf | sudo tee -a /etc/raspap/networking/defaults > /dev/null
echo "Changing file ownership of $raspap_dir"
sudo chown -R $raspap_user:$raspap_user "$raspap_dir" || _install_status 1 "Unable to change file ownership for '$raspap_dir'"
}

View File

@ -35,7 +35,7 @@ echo "Checking iptables rules"
rules=(
"-A POSTROUTING -o tun0 -j MASQUERADE"
"-A FORWARD -i tun0 -o ${interface} -m state --state RELATED,ESTABLISHED -j ACCEPT"
"-A FORWARD -i wlan0 -o tun0 -j ACCEPT"
"-A FORWARD -i ${interface} -o tun0 -j ACCEPT"
)
for rule in "${rules[@]}"; do

View File

@ -0,0 +1,40 @@
#!/bin/bash
#
# RaspAP feature installation: handling of mobile data clients and client configuration
# to be sources by the RaspAP installer script
# Author: @zbchristian <christian@zeitnitz.eu>
# Author URI: https://github.com/zbchristian/
# License: GNU General Public License v3.0
# License URI: https://github.com/raspap/raspap-webgui/blob/master/LICENSE
# path for mobile modem scripts
readonly raspap_clients_scripts="/usr/local/sbin"
#
# table of mobile network operators - links the 5 digit operator code (from the modem) with a clear text operator name
readonly raspap_clients_operator_table="https://raw.githubusercontent.com/musalbas/mcc-mnc-table/master/mcc-mnc-table.csv"
function _install_feature_clients() {
name="feature clients"
_install_log "Install $name"
_install_log " - required packages for mobile data clients"
sudo apt-get install wvdial socat bc || _install_status 1 "Unable to install dependencies for $name"
_install_log " - copy configuration files and scripts"
# Move scripts
sudo cp "$webroot_dir/config/client_config/"*.sh "$raspap_clients_scripts/" || _install_status 1 "Unable to move client scripts ($name)"
sudo chmod a+rx "$raspap_clients_scripts/"*.sh || _install_status 1 "Unable to chmod client scripts ($name)"
# wget $raspap_clients_operator_table -o "$raspap_clients_scripts/"mcc-mnc-table.csv || _install_status 1 "Unable to wget operator table ($name)"
sudo cp "$webroot_dir/config/client_config/mcc-mnc-table.csv" "$raspap_clients_scripts/" || _install_status 1 "Unable to move client data ($name)"
# wvdial settings
sudo cp "$webroot_dir/config/client_config/wvdial.conf" "/etc/" || _install_status 1 "Unable to install client configuration ($name)"
sudo cp "$webroot_dir/config/client_config/interfaces" "/etc/network/interfaces" || _install_status 1 "Unable to install interface settings ($name)"
# udev rules/services to auto start mobile data services
sudo cp "$webroot_dir/config/client_config/70-mobile-data-sticks.rules" "/etc/udev/rules.d/" || _install_status 1 "Unable to install client udev rules ($name)"
sudo cp "$webroot_dir/config/client_config/80-raspap-net-devices.rules" "/etc/udev/rules.d/" || _install_status 1 "Unable to install client udev rules ($name)"
sudo cp "$webroot_dir/config/client_config/"*.service "/etc/systemd/system/" || _install_status 1 "Unable to install client startup services ($name)"
# client configuration and udev rule templates
sudo cp "$webroot_dir/config/client_udev_prototypes.json" "/etc/raspap/networking/" || _install_status 1 "Unable to install client configuration ($name)"
_install_status 0
}

View File

@ -30,6 +30,8 @@ www-data ALL=(ALL) NOPASSWD:/sbin/reboot
www-data ALL=(ALL) NOPASSWD:/sbin/ip link set wlan[0-9] down
www-data ALL=(ALL) NOPASSWD:/sbin/ip link set wlan[0-9] up
www-data ALL=(ALL) NOPASSWD:/sbin/ip -s a f label wlan[0-9]
www-data ALL=(ALL) NOPASSWD:/sbin/ifup *
www-data ALL=(ALL) NOPASSWD:/sbin/ifdown *
www-data ALL=(ALL) NOPASSWD:/bin/cp /etc/raspap/networking/dhcpcd.conf /etc/dhcpcd.conf
www-data ALL=(ALL) NOPASSWD:/etc/raspap/hostapd/enablelog.sh
www-data ALL=(ALL) NOPASSWD:/etc/raspap/hostapd/disablelog.sh
@ -45,6 +47,12 @@ www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/dnsmasq_custom /etc/raspap/adblock/cust
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/wgdata /etc/wireguard/*.conf
www-data ALL=(ALL) NOPASSWD:/bin/mv /tmp/wg-*.key /etc/wireguard/wg-*.key
www-data ALL=(ALL) NOPASSWD:/etc/raspap/adblock/update_blocklist.sh
www-data ALL=(ALL) NOPASSWD:/usr/bin/socat - /dev/ttyUSB[0-9]
www-data ALL=(ALL) NOPASSWD:/usr/local/sbin/onoff_huawei_hilink.sh *
www-data ALL=(ALL) NOPASSWD:/bin/sed -i * /etc/wvdial.conf
www-data ALL=(ALL) NOPASSWD:/bin/sed -i * /etc/udev/rules.d/80-raspap-net-devices.rules
www-data ALL=(ALL) NOPASSWD:/usr/bin/tee -a /etc/udev/rules.d/80-raspap-net-devices.rules
www-data ALL=(ALL) NOPASSWD:/usr/local/sbin/switchClientState.sh *
www-data ALL=(ALL) NOPASSWD:/usr/bin/tee /tmp/wireguard.log
www-data ALL=(ALL) NOPASSWD:/bin/systemctl * wg-quick@wg0
www-data ALL=(ALL) NOPASSWD:/usr/bin/wg
@ -52,4 +60,3 @@ www-data ALL=(ALL) NOPASSWD:/bin/cat /etc/wireguard/*.conf
www-data ALL=(ALL) NOPASSWD:/bin/cat /etc/wireguard/wg-*.key
www-data ALL=(ALL) NOPASSWD:/bin/rm /etc/wireguard/*.conf
www-data ALL=(ALL) NOPASSWD:/bin/rm /etc/wireguard/wg-*.key

View File

@ -38,6 +38,7 @@ set -eo pipefail
function _main() {
# set defaults
repo="RaspAP/raspap-webgui" # override with -r, --repo option
repo_common="$repo"
_parse_params "$@"
_setup_colors
_log_output
@ -72,6 +73,7 @@ function _parse_params() {
;;
-r|--repo|--repository)
repo="$2"
repo_common="$repo"
shift
;;
-b|--branch)
@ -184,6 +186,7 @@ function _get_release() {
readonly RASPAP_LATEST=$(curl -s "https://api.github.com/repos/$repo/releases/latest" | grep -Po '"tag_name": "\K.*?(?=")' )
if [ "$insiders" == 1 ]; then
repo="RaspAP/raspap-insiders"
repo_common="RaspAP/raspap-webgui"
readonly RASPAP_INSIDERS_LATEST=$(curl -s "https://api.raspap.com/repos/RaspAP/raspap-insiders/releases/latest/" | grep -Po '"tag_name": "\K.*?(?=")' )
readonly RASPAP_RELEASE="${RASPAP_INSIDERS_LATEST} Insiders"
else
@ -237,7 +240,11 @@ function _load_installer() {
header=(--header "Authorization: token $acctoken")
fi
UPDATE_URL="https://raw.githubusercontent.com/$repo/$branch/"
UPDATE_URL="https://raw.githubusercontent.com/$repo_common/$branch/"
header=()
if [[ ! -z "$acctoken" ]]; then
header=(--header "Authorization: token $acctoken")
fi
if [ "${install_cert:-}" = 1 ]; then
source="mkcert"
wget "${header[@]}" -q ${UPDATE_URL}installers/${source}.sh -O /tmp/raspap_${source}.sh

Binary file not shown.

View File

@ -244,6 +244,60 @@ msgstr "Stop wlan0"
msgid "Connected Devices"
msgstr "Connected Devices"
msgid "Client: Ethernet cable"
msgstr "Client: Ethernet cable"
msgid "Ethernet"
msgstr "Ethernet"
msgid "Client: Smartphone (USB tethering)"
msgstr "Client: Smartphone (USB tethering)"
msgid "Smartphone"
msgstr "Smartphone"
msgid "WiFi"
msgstr "WiFi"
msgid "Mobile Data Client"
msgstr "Mobile Data Client"
msgid "Mobile Data"
msgstr "Mobile Data"
msgid "No information available"
msgstr "No information available"
msgid "Interface name invalid"
msgstr "Interface name invalid"
msgid "Required exec function is disabled. Check if exec is not added to php <code>disable_functions</code>."
msgstr "Required exec function is disabled. Check if exec is not added to php <code>disable_functions</code>."
msgid "Waiting for the interface to start ..."
msgstr "Waiting for the interface to start ..."
msgid "Stop the Interface"
msgstr "Stop the Interface"
msgid "Connection mode"
msgstr "Connection mode"
msgid "Signal quality"
msgstr "Signal quality"
msgid "WAN IP"
msgstr "WAN IP"
msgid "Web-GUI"
msgstr "Web-GUI"
msgid "Signal strength"
msgstr "Signal strength"
msgid "No Client device or not yet configured"
msgstr "No Client device or not yet configured"
#: includes/dhcp.php
msgid "DHCP server settings"
msgstr "DHCP server settings"
@ -538,6 +592,57 @@ msgstr "Apply settings"
msgid "Information provided by /sys/class/net"
msgstr "Information provided by /sys/class/net"
msgid "Network Devices"
msgstr "Network Devices"
msgid "Mobile Data Settings"
msgstr "Mobile Data Settings"
msgid "Properties of network devices"
msgstr "Properties of network devices"
msgid "Device"
msgstr "Device"
msgid "MAC"
msgstr "MAC"
msgid "USB vid/pid"
msgstr "USB vid/pid"
msgid "Device type"
msgstr "Device type"
msgid "Fixed name"
msgstr "Fixed name"
msgid "Change"
msgstr "Change"
msgid "Settings for Mobile Data Devices"
msgstr "Settings for Mobile Data Devices"
msgid "PIN of SIM card"
msgstr "PIN of SIM card"
msgid "APN Settings (Modem device ppp0)"
msgstr "APN Settings (Modem device ppp0)"
msgid "Access Point Name (APN)"
msgstr "Access Point Name (APN)"
msgid "Password"
msgstr "Password"
msgid "Successfully Updated Network Configuration"
msgstr "Successfully Updated Network Configuration"
msgid "Error saving network configuration to file"
msgstr "Error saving network configuration to file"
msgid "Unable to detect interface"
msgstr "Unable to detect interface"
#: includes/system.php
msgid "System Information"
msgstr "System Information"

View File

@ -3,18 +3,17 @@
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<i class="fas fa-tachometer-alt fa-fw mr-2"></i><?php echo _("Dashboard"); ?>
</div>
<div class="col">
<button class="btn btn-light btn-icon-split btn-sm service-status float-right">
<span class="icon"><i class="fas fa-circle service-status-<?php echo $ifaceStatus ?>"></i></span>
<span class="text service-status"><?php echo strtolower($apInterface) .' '. _($ifaceStatus) ?></span>
</button>
</div>
<div class="col">
<i class="fas fa-tachometer-alt fa-fw mr-2"></i><?php echo _("Dashboard"); ?>
</div>
<div class="col">
<button class="btn btn-light btn-icon-split btn-sm service-status float-right">
<span class="icon"><i class="fas fa-circle service-status-<?php echo $ifaceStatus ?>"></i></span>
<span class="text service-status"><?php echo $type_name; if ( $isClientConfigured ) echo ' '. _($ifaceStatus); ?></span>
</button>
</div>
</div><!-- /.row -->
</div><!-- /.card-header -->
<div class="card-body">
<div class="row">
@ -33,37 +32,97 @@
<div class="col-sm-6 align-items-stretch">
<div class="card h-100">
<div class="card-body wireless">
<h4 class="card-title"><?php echo _("Wireless Client"); ?></h4>
<h4 class="card-title"><?php echo _("$client_title"); ?></h4>
<div class="row ml-1">
<div class="col-sm">
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Connected To"); ?></div><div class="info-value col-xs-3"><?php echo htmlspecialchars($connectedSSID, ENT_QUOTES); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Interface"); ?></div><div class="info-value col-xs-3"><?php echo htmlspecialchars($clientInterface); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("AP Mac Address"); ?></div><div class="info-value col-xs-3"><?php echo htmlspecialchars($connectedBSSID, ENT_QUOTES); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Bitrate"); ?></div><div class="info-value col-xs-3"><?php echo htmlspecialchars($bitrate, ENT_QUOTES); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Signal Level"); ?></div><div class="info-value col-xs-3"><?php echo htmlspecialchars($signalLevel, ENT_QUOTES); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Transmit Power"); ?></div><div class="info-value col-xs-3"><?php echo htmlspecialchars($txPower, ENT_QUOTES); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Frequency"); ?></div><div class="info-value col-xs-3"><?php echo htmlspecialchars($frequency, ENT_QUOTES); ?></div>
</div>
</div>
<div class="col-md d-flex">
<script>var linkQ = <?php echo json_encode($strLinkQuality); ?>;</script>
<div class="chart-container">
<canvas id="divChartLinkQ"></canvas>
</div>
<?php $valEcho=function($cl,$id) {$val = isset($cl[$id])&& !empty($cl[$id]) ? $cl[$id] : "-"; echo htmlspecialchars($val,ENT_QUOTES);} ?>
<?php if ($clientinfo["type"] == "wlan") : // WIRELESS ?>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Connected To"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"ssid"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("AP Mac Address"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"ap-mac"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Bitrate"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"bitrate"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Signal Level"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"signal"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Transmit Power"); ?></div><div class="info-value col-xs-3"><?php echo htmlspecialchars($txPower, ENT_QUOTES); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Frequency"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"freq"); ?></div>
</div>
<?php elseif ($clientinfo["type"] == "phone" ) : // Smartphones (tethering over USB) ?>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Device"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"vendor")." ". $valEcho($clientinfo,"model"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("IP Address"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"ipaddress"); ?></div>
</div>
<?php elseif ($clientinfo["type"] == "hilink" ) : // MOBILE DATA - ROUTER MODE (HILINK) ?>
<?php
exec('ip route list | sed -rn "s/default via (([0-9]{1,3}\.){3}[0-9]{1,3}).*dev '.$clientinfo["name"].'.*/\1/p"',$gw); // get gateway
$gw=empty($gw) ? "" : $gw[0];
?>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Device"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"model")." (Hilink)"; ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Connection mode"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"mode"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Signal quality"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"signal"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Network"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"operator"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("WAN IP"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"wan_ip"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Web-GUI"); ?></div><div class="info-value col-xs-3"><?php if(!empty($gw)) echo '<a href="http://'.$gw.'" >'.$gw."</a>"; ?></div>
</div>
<?php elseif ($clientinfo["type"] == "ppp" ) : // MOBILE DATA MODEM) ?>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Device"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"model"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Connection mode"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"mode"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Signal strength"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"signal"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Network"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"operator"); ?></div>
</div>
<?php elseif ($clientinfo["type"] == "eth" ) : // ETHERNET ?>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Device"); ?></div><div class="info-value col-xs-3"><?php $valEcho($clientinfo,"vendor")." ".$valEcho($clientinfo,"model"); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("IP Address"); ?></div><div class="info-value col-xs-3"><?php echo $valEcho($clientinfo,"ipaddress"); ?></div>
</div>
<?php else : // NO CLIENT ?>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("No Client device or not yet configured"); ?></div>
</div>
<?php endif; ?>
</div>
<?php if ($isClientConfigured) : ?>
<div class="col-md d-flex">
<?php
preg_match("/.*\((\s*\d*)\s*%\s*\)/",$clientinfo["signal"],$match);
$strLinkQuality=array_key_exists(1,$match) ? $match[1] : 0;
?>
<script>var linkQ = <?php echo json_encode($strLinkQuality); ?>;</script>
<div class="chart-container">
<canvas id="divChartLinkQ"></canvas>
</div>
</div>
<?php endif; ?>
</div><!--row-->
</div><!-- /.card-body -->
</div><!-- /.card -->
@ -93,7 +152,7 @@
<?php endif; ?>
<?php foreach (array_slice($clients,0, 2) as $client) : ?>
<tr>
<?php if ($arrHostapdConf['BridgedEnable'] == 1): ?>
<?php if ($bridgedEnable == 1): ?>
<td><?php echo htmlspecialchars($client, ENT_QUOTES) ?></td>
<?php else : ?>
<?php $props = explode(' ', $client) ?>
@ -117,28 +176,41 @@
</div><!-- /.card -->
</div><!-- /.col-md-6 -->
</div><!-- /.row -->
<div class="col-lg-12 mt-3">
<div class="row">
<form action="wlan0_info" method="POST">
<?php echo CSRFTokenFieldTag() ?>
<?php echo CSRFTokenFieldTag(); ?>
<?php if (!RASPI_MONITOR_ENABLED) : ?>
<?php if (!$wlan0up) : ?>
<input type="submit" class="btn btn-success" value="<?php echo _("Start").' '.$clientInterface ?>" name="ifup_wlan0" />
<?php else : ?>
<input type="submit" class="btn btn-warning" value="<?php echo _("Stop").' '.$clientInterface ?>" name="ifdown_wlan0" />
<?php if ($ifaceStatus == "down") : ?>
<input type="submit" class="btn btn-success" value="<?php echo _("Start").' '.$type_name ?>" name="ifup_wlan0" data-toggle="modal" data-target="#switchClientModal"/>
<?php elseif ($ifaceStatus == "up") : ?>
<input type="submit" class="btn btn-warning" value="<?php echo _("Stop").' '.$type_name ?>" name="ifdown_wlan0" data-toggle="modal" data-target="#switchClientModal"/>
<?php endif ?>
<?php endif ?>
<button type="button" onClick="window.location.reload();" class="btn btn-outline btn-primary"><i class="fas fa-sync-alt"></i> <?php echo _("Refresh") ?></a>
<button type="button" onClick="window.location.reload();" class="btn btn-outline btn-primary"><i class="fas fa-sync-alt"></i> <?php echo _("Refresh") ?></button>
</form>
</div>
</div>
</div><!-- /.card-body -->
<div class="card-footer"><?php echo _("Information provided by ip and iw and from system"); ?></div>
</div><!-- /.card -->
</div><!-- /.col-lg-12 -->
</div><!-- /.row -->
<!-- Modal -->
<div class="modal fade" id="switchClientModal" tabindex="-1" role="dialog" aria-labelledby="ModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<div class="modal-title" id="ModalLabel">
<i class="fas fa-sync-alt mr-2"></i>
<?php if($ifaceStatus=="down") echo _("Waiting for the interface to start ..."); else echo _("Stop the Interface"); ?>
</div>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span>
</div>
</div>
</div>
<script type="text/javascript"<?php //echo ' nonce="'.$csp_page_nonce.'"'; ?>>
// js translations:
var t = new Array();

View File

@ -1,23 +1,27 @@
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<i class="fas fa-network-wired mr-2"></i><?php echo _("Networking"); ?>
</div>
</div><!-- ./row -->
</div><!-- ./card-header -->
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<i class="fas fa-network-wired mr-2"></i><?php echo _("Networking"); ?>
</div>
</div><!-- ./row -->
</div><!-- ./card-header -->
<div class="card-body">
<div id="msgNetworking"></div>
<ul class="nav nav-tabs">
<li role="presentation" class="nav-item"><a class="nav-link active" href="#summary" aria-controls="summary" role="tab" data-toggle="tab"><?php echo _("Summary"); ?></a></li>
<?php if (!$bridgedEnabled) : // no interface details when bridged ?>
<li role="presentation" class="nav-item"><a class="nav-link" href="#netdevices" aria-controls="netdevices" role="tab" data-toggle="tab"><?php echo _("Network Devices"); ?></a></li>
<li role="presentation" class="nav-item"><a class="nav-link" href="#mobiledata" aria-controls="mobiledata" role="tab" data-toggle="tab"><?php echo _("Mobile Data Settings"); ?></a></li>
<?php endif ?>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="summary">
<h4 class="mt-3"><?php echo _("Internet connection"); ?></h4>
<div class="row">
<div class="col-sm-12"">
<div class="col-sm-12">
<div class="card ">
<div class="card-body">
<div class="table-responsive">
@ -74,9 +78,123 @@
<div class="col-lg-12">
<div class="row">
<button type="button" onClick="window.location.reload();" class="btn btn-outline btn-primary"><i class="fas fa-sync-alt"></i> <?php echo _("Refresh") ?></a>
</div>
</div>
</div>
</div>
</div>
<?php $arrMD = file_exists(($f = RASPI_CONFIG."/networking/mobiledata.ini")) ? parse_ini_file($f) : false;
if ($arrMD==false) { $arrMD=[]; $arrMD["pin"]=$arrMD["apn"]=$arrMD["apn_user"]=$arrMD["apn_pw"]=$arrMD["router_user"]=$arrMD["router_pw"]=""; }
?>
<div role="tabpanel" class="tab-pane fade in" id="netdevices">
<h4 class="mt-3"><?php echo _("Properties of network devices") ?></h4>
<div class="row">
<div class="col-sm-12">
<div class="card ">
<div class="card-body">
<form id="frm-netdevices">
<?php echo CSRFTokenFieldTag() ?>
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th><?php echo _("Device"); ?></th>
<th><?php echo _("Interface"); ?></th>
<th></th>
<th><?php echo _("MAC"); ?></th>
<th><?php echo _("USB vid/pid"); ?></th>
<th><?php echo _("Device type"); ?></th>
<th style="min-width:6em"><?php echo _("Fixed name"); ?></th>
<th></th>
</tr>
</thead>
<tbody>
<?php
if(!empty($clients)) {
$ncl=$clients["clients"];
if($ncl > 0) {
foreach($clients["device"] as $id => $dev) {
echo "<tr>";
echo "<td>".$dev["vendor"]." ".$dev["model"]."</td>\n";
echo "<td>".$dev["name"]."</td>\n";
$ty="Client";
if(isset($dev["isAP"]) && $dev["isAP"]) $ty="Access Point";
echo "<td>".$ty."</td>\n";
echo "<td>".$dev["mac"]."</td>\n";
if(isset($dev["vid"]) && !empty($dev["vid"])) echo "<td>".$dev["vid"]."/".$dev["pid"]."</td>\n";
else echo "<td> - </td>\n";
$udevfile=$_SESSION["udevrules"]["udev_rules_file"];
$isStatic=array();
exec('find /etc/udev/rules.d/ -type f \( -iname "*.rules" ! -iname "'.basename($udevfile).'" \) -exec grep -i '.$dev["mac"].' {} \; ',$isStatic);
if(empty($isStatic))
exec('find /etc/udev/rules.d/ -type f \( -iname "*.rules" ! -iname "'.basename($udevfile).'" \) -exec grep -i '.$dev["vid"].' {} \; | grep -i '.$dev["pid"].' ',$isStatic);
$isStatic = empty($isStatic) ? false : true;
$devname=array();
exec('grep -i '.$dev["vid"].' '.$udevfile.' | grep -i '.$dev["pid"].' | sed -rn \'s/.*name=\"(\w*)\".*/\1/ip\' ',$devname);
if(!empty($devname)) $devname=$devname[0];
else {
exec('grep -i '.$dev["mac"].' '.$udevfile.' | sed -rn \'s/.*name=\"(\w*)\".*/\1/ip\' ',$devname);
if(!empty($devname)) $devname=$devname[0];
}
if(empty($devname)) $devname="";
$isStatic = $isStatic || in_array($dev["type"],array("ppp","tun"));
$txtdisabled=$isStatic ? "disabled":"";
echo '<td><select '.$txtdisabled.' class="selectpicker form-control" id="int-new-type-'.$dev["name"].'">';
foreach($_SESSION["net-device-types"] as $i => $type) {
$txt=$_SESSION["net-device-types-info"][$i];
$txtdisabled = in_array($type,array("ppp","tun")) ? "disabled":"";
if(preg_match("/^".$_SESSION["net-device-name-prefix"][$i].".*$/",$dev["type"])===1) echo '<option '.$txtdisabled.' selected value="'.$type.'">'.$txt.'</option>';
else echo '<option '.$txtdisabled.' value="'.$type.'">'.$txt.'</option>';
}
echo "</select></td>";
echo '<td>';
if (! $isStatic ) echo '<input type="text" class="form-control" id="int-name-'.$dev["name"].'" value="'.$devname.'" >'."\n";
else echo $dev["name"];
echo '<input type="hidden" class="form-control" id="int-vid-'.$dev["name"].'" value="'.$dev["vid"].'" >'."\n";
echo '<input type="hidden" class="form-control" id="int-pid-'.$dev["name"].'" value="'.$dev["pid"].'" >'."\n";
echo '<input type="hidden" class="form-control" id="int-mac-'.$dev["name"].'" value="'.$dev["mac"].'" >'."\n";
echo '<input type="hidden" class="form-control" id="int-type-'.$dev["name"].'" value="'.$dev["type"].'" >'."\n";
echo '</td>'."\n";
echo '<td>';
if (! $isStatic) echo '<a href="#" class="btn btn-secondary intsave" data-opts="'.$dev["name"].'" data-int="netdevices">' ._("Change").'</a>';
echo "</td>\n";
echo "</tr>\n";
}
}
} else echo "<tr><td colspan=4>No network devices found</td></tr>";
?>
</tbody>
</table>
</div>
</form>
</div>
</div>
</div>
</div>
</div><!-- /.tab-panel -->
<div role="tabpanel" class="tab-pane fade in" id="mobiledata">
<div class="row">
<div class="col-lg-6">
<h4 class="mt-3"><?php echo _("Settings for Mobile Data Devices") ?></h4>
<hr />
<form id="frm-mobiledata">
<?php echo CSRFTokenFieldTag() ?>
<div class="form-group">
<label for="pin-mobile"><?php echo _("PIN of SIM card") ?></label>
<input type="number" class="form-control" id="pin-mobile" placeholder="1234" value="<?php echo $arrMD["pin"]?>" >
</div>
<h4 class="mt-3"><?php echo _("APN Settings (Modem device ppp0)") ?></h4>
<div class="form-group">
<label for="apn-mobile"><?php echo _("Access Point Name (APN)") ?></label>
<input type="text" class="form-control" id="apn-mobile" placeholder="web.myprovider.com" value="<?php echo $arrMD["apn"]?>" >
<label for="apn-user-mobile"><?php echo _("Username") ?></label>
<input type="text" class="form-control" id="apn-user-mobile" value="<?php echo $arrMD["apn_user"]?>" >
<label for="apn-pw-mobile"><?php echo _("Password") ?></label>
<input type="text" class="form-control" id="apn-pw-mobile" value="<?php echo $arrMD["apn_pw"]?>" >
</div>
<a href="#" class="btn btn-outline btn-primary intsave" data-int="mobiledata"><?php echo _("Save settings") ?></a>
</form>
</div>
</div>
</div><!-- /.tab-panel -->
</div>
</div><!-- /.card-body -->
<div class="card-footer"><?php echo _("Information provided by /sys/class/net"); ?></div>