Combine Dependencies; Other Improvements

-Removed CPU intensive python based telnet server option
-Removed Micropython
-Renamed AT Telnet Daemon socat-at bridge
-Moved TTL related files not part of the www/cgi-bin directory to /simplefirewall
-Improved Simplefirewall menu, added ability to change TTL
-Combined uninstall and install functions for simpleadmin and dependencies into single functions
This commit is contained in:
iamromulan
2024-02-20 23:44:05 -05:00
parent c83f703da6
commit 780590bfa5
31 changed files with 288 additions and 1767 deletions

View File

@@ -1,29 +1,37 @@
#!/bin/sh
# Define paths
USRDATA_DIR="/usrdata"
MICROPYTHON_DIR="/usrdata/micropython"
AT_TELNET_DIR="/usrdata/at-telnet"
AT_TELNET_SYSD_DIR="/usrdata/at-telnet/systemd_units"
AT_TELNET_SMD7_SYSD_DIR="/usrdata/at-telnet/smd7_systemd_units"
SIMPLE_ADMIN_DIR="/usrdata/simpleadmin"
# Define toolkit paths
GITTREE="development"
TMP_DIR="/tmp"
GITHUB_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/main.zip"
GITHUB_SIMPADMIN_FULL_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadminfull.zip"
GITHUB_SIMPADMIN_NOCMD_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadminnoatcmds.zip"
GITHUB_SIMPADMIN_TTL_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadminttlonly.zip"
GITHUB_SIMPADMIN_TEST_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadmintest.zip"
TAILSCALE_DIR="/usrdata/tailscale/"
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
USRDATA_DIR="/usrdata"
SOCAT_AT_DIR="/usrdata/socat-at-bridge"
SOCAT_AT_SYSD_DIR="/usrdata/socat-at-bridge/systemd_units"
SOCAT_AT_SMD7_SYSD_DIR="/usrdata/socat-at-bridge/smd7_systemd_units"
SIMPLE_ADMIN_DIR="/usrdata/simpleadmin"
SIMPLE_FIREWALL_DIR="/usrdata/simplefirewall"
SIMPLE_FIREWALL_SCRIPT="$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
SIMPLE_FIREWALL_SYSTEMD_DIR="$SIMPLE_FIREWALL_DIR/systemd"
SIMPLE_FIREWALL_SERVICE="/lib/systemd/system/simplefirewall.service"
GITHUB_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/$GITTREE.zip"
GITHUB_SIMPADMIN_FULL_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadminfullatcmds.zip"
GITHUB_SIMPADMIN_TTL_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadminttlonly.zip"
GITHUB_SIMPADMIN_TEST_URL="https://github.com/iamromulan/quectel-rgmii-toolkit/archive/refs/heads/simpleadmintest.zip"
TAILSCALE_DIR="/usrdata/tailscale/"
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
# AT Command Script Variables and Functions
DEVICE_FILE="/dev/smd7"
TIMEOUT=4 # Set a timeout for the response
# Function to remount file system as read-write
remount_rw() {
mount -o remount,rw /
}
# Function to remount file system as read-only
remount_ro() {
mount -o remount,ro /
}
# Basic AT commands without socat bridge for fast responce commands only
start_listening() {
cat "$DEVICE_FILE" > /tmp/device_readout &
CAT_PID=$!
@@ -93,195 +101,40 @@ send_at_commands() {
fi
}
# Function to remount file system as read-write
remount_rw() {
mount -o remount,rw /
}
# Function to remount file system as read-only
remount_ro() {
mount -o remount,ro /
}
# Check if AT Telnet Daemon is installed
is_at_telnet_installed() {
[ -d "$MICROPYTHON_DIR" ] && return 0 || return 1
[ -d "$AT_TELNET_DIR" ] && return 0 || return 1
}
# Function to check if Simple Firewall is installed
is_simple_firewall_installed() {
if [ -d "$SIMPLE_FIREWALL_DIR" ]; then
return 0
else
return 1
fi
}
# Check if Simple Admin is installed
is_simple_admin_installed() {
[ -d "$SIMPLE_ADMIN_DIR" ] && return 0 || return 1
}
# Function to install/update Simple Firewall
install_update_simple_firewall() {
echo "Installing/Updating Simple Firewall..."
mount -o remount,rw /
mkdir -p "$SIMPLE_FIREWALL_DIR"
mkdir -p "$SIMPLE_FIREWALL_SYSTEMD_DIR"
wget -O "$SIMPLE_FIREWALL_SCRIPT" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/simplefirewall/simplefirewall.sh
chmod +x "$SIMPLE_FIREWALL_SCRIPT"
wget -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/simplefirewall.service" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/simplefirewall/systemd/simplefirewall.service
cp -f "$SIMPLE_FIREWALL_SYSTEMD_DIR/simplefirewall.service" "$SIMPLE_FIREWALL_SERVICE"
ln -sf "$SIMPLE_FIREWALL_SERVICE" "/lib/systemd/system/multi-user.target.wants/"
systemctl daemon-reload
systemctl restart simplefirewall
mount -o remount,ro /
echo "Simple Firewall installation/update complete."
}
# Function to uninstall Simple Firewall
uninstall_simple_firewall() {
echo "Uninstalling Simple Firewall..."
mount -o remount,rw /
systemctl stop simplefirewall
rm -f "/lib/systemd/system/multi-user.target.wants/simplefirewall.service"
rm -f "$SIMPLE_FIREWALL_SERVICE"
rm -rf "$SIMPLE_FIREWALL_DIR"
systemctl daemon-reload
mount -o remount,ro /
echo "Simple Firewall uninstalled."
}
# Function to configure Simple Firewall
configure_simple_firewall() {
if [ ! -f "$SIMPLE_FIREWALL_SCRIPT" ]; then
echo "Simple Firewall script not found."
return
fi
# Extract current ports configuration
current_ports_line=$(grep '^PORTS=' "$SIMPLE_FIREWALL_SCRIPT")
ports=$(echo "$current_ports_line" | cut -d'=' -f2 | tr -d '()' | tr ' ' '\n' | grep -o '[0-9]\+')
echo "$ports" | awk '{print NR") "$0}'
while true; do
echo "Enter a port number to add/remove, or type 'done' to finish:"
read port
if [ "$port" = "done" ]; then
break
elif ! echo "$port" | grep -qE '^[0-9]+$'; then
echo "Invalid input: Please enter a numeric value."
elif echo "$ports" | grep -q "^$port\$"; then
# Remove port
ports=$(echo "$ports" | grep -v "^$port\$")
echo "Port $port removed."
else
# Add port
ports=$(echo "$ports"; echo "$port" | grep -o '[0-9]\+')
echo "Port $port added."
fi
done
# Prepare updated ports line
new_ports_line="PORTS=($(echo "$ports" | tr '\n' ' '))"
# Update the script with new ports
sed -i "s/$current_ports_line/$new_ports_line/" "$SIMPLE_FIREWALL_SCRIPT"
systemctl restart simplefirewall
echo "Firewall configuration updated."
}
# Function for Simplefirewall Submenu
simplefirewall_menu() {
while true; do
echo "Simple Firewall Management"
echo "1) Install/Update/Uninstall Simple Firewall"
echo "2) Configure Simple Firewall"
echo "3) Exit"
read -p "Enter your choice: " choice
case $choice in
1)
if is_simple_firewall_installed; then
echo "Simple Firewall is already installed."
echo "1) Update Simple Firewall"
echo "2) Uninstall Simple Firewall"
read -p "Enter your choice: " update_uninstall_choice
case $update_uninstall_choice in
1) install_update_simple_firewall;;
2) uninstall_simple_firewall;;
*) echo "Invalid option";;
esac
else
install_update_simple_firewall
fi
;;
2)
configure_simple_firewall
;;
3)
echo "Exiting..."
break
;;
*)
echo "Invalid option"
;;
esac
done
}
# Function to install/update AT Telnet Daemon
install_update_at_telnet() {
# Function to install/update AT Socat Bridge
install_update_at_socat() {
remount_rw
mkdir $MICROPYTHON_DIR
mkdir $AT_TELNET_DIR
cd $MICROPYTHON_DIR
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/errno.py
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/fcntl.py
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/ffilib.py
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/logging.py
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/micropython
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/os_compat.py
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/serial.py
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/stat.py
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/time.py
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/micropython/traceback.mpy
cd $AT_TELNET_DIR
mkdir $AT_TELNET_SYSD_DIR
mkdir $AT_TELNET_SMD7_SYSD_DIR
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/modem-multiclient.py
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/picocom
mkdir "$SOCAT_AT_DIR"
cd "$SOCAT_AT_DIR"
mkdir $SOCAT_AT_SYSD_DIR
mkdir $SOCAT_AT_SMD7_SYSD_DIR
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/socat-armel-static
cd $AT_TELNET_SYSD_DIR
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/systemd_units/socat-smd11.service
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/systemd_units/at-telnet-daemon.service
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/systemd_units/socat-smd11-from-ttyIN.service
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/systemd_units/socat-smd11-to-ttyIN.service
cd $AT_TELNET_SMD7_SYSD_DIR
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/smd7_systemd_units/at-telnet-daemon.service
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/smd7_systemd_units/socat-smd7-from-ttyIN.service
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/smd7_systemd_units/socat-smd7-to-ttyIN.service
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/attelnetdaemon/at-telnet/smd7_systemd_units/socat-smd7.service
# Set execute permissions
chmod +x $MICROPYTHON_DIR/micropython
chmod +x $AT_TELNET_DIR/modem-multiclient.py
chmod +x $AT_TELNET_DIR/socat-armel-static
chmod +x $AT_TELNET_DIR/picocom
chmod +x "$SOCAT_AT_DIR"/socat-armel-static
# User prompt for selecting device
echo "Which device should AT over Telnet use?"
echo "Which device should Simpleadmin use?"
echo "This will create virtual tty ports (serial ports) that will use either smd11 or smd7"
echo "1) Use smd11 (default)"
echo "2) Use smd7 (use this if another application is using smd11)"
echo "2) Use smd7 (use this if another application is using smd11 already)"
read -p "Enter your choice (1 or 2): " device_choice
# Stop and disable existing services before installing new ones
echo -e "\033[0;32mThese errors are OK, script tries to remove all first in case you are updating\033[0m"
systemctl stop at-telnet-daemon
systemctl disable at-telnet-daemon
systemctl stop socat-smd11
@@ -298,7 +151,8 @@ install_update_at_telnet() {
rm /lib/systemd/system/socat-smd7-to-ttyIN.service
rm /lib/systemd/system/socat-smd7-from-ttyIN.service
systemctl daemon-reload
echo -e "\033[0;32mThese errors are OK, script tries to remove all first in case you are updating\033[0m"
# Depending on the choice, copy the respective systemd unit files
case $device_choice in
2)
@@ -311,6 +165,7 @@ install_update_at_telnet() {
sleep 2s
systemctl start socat-smd7-to-ttyIN
systemctl start socat-smd7-from-ttyIN
cd /
;;
1)
cp -f $AT_TELNET_SYSD_DIR/*.service /lib/systemd/system
@@ -322,195 +177,203 @@ install_update_at_telnet() {
sleep 2s
systemctl start socat-smd11-to-ttyIN
systemctl start socat-smd11-from-ttyIN
cd /
;;
esac
# User prompt for enabling Telnet server
echo "-Telnet server is not required for simpleadmin"
echo "-Simpleadmin uses the tty port created in the previous step"
echo "-If enabled a telnet server will listen on the gateway address on port 5000"
echo "-It isn't password protceted though so it is recommended to only enable if you need it"
echo "Enable Telnet server?"
echo "1) Yes"
echo "2) No"
read -p "Enter your choice (1 or 2): " telnet_choice
# Link or remove systemd files based on user choice
if [ "$telnet_choice" = "1" ]; then
ln -sf /lib/systemd/system/at-telnet-daemon.service /lib/systemd/system/multi-user.target.wants/
# Start Services
systemctl start at-telnet-daemon
remount_ro
else
remount_ro
fi
}
# Function to remove AT Telnet Daemon
remove_at_telnet() {
remount_rw
# Stop and disable all possible services related to AT Telnet Daemon
systemctl stop at-telnet-daemon
systemctl disable at-telnet-daemon
systemctl stop socat-smd11
systemctl stop socat-smd11-to-ttyIN
systemctl stop socat-smd11-from-ttyIN
systemctl stop socat-smd7
systemctl stop socat-smd7-to-ttyIN
systemctl stop socat-smd7-from-ttyIN
# Remove all systemd service files for both smd11 and smd7 configurations
rm /lib/systemd/system/at-telnet-daemon.service
rm /lib/systemd/system/socat-smd11.service
rm /lib/systemd/system/socat-smd11-to-ttyIN.service
rm /lib/systemd/system/socat-smd11-from-ttyIN.service
rm /lib/systemd/system/socat-smd7.service
rm /lib/systemd/system/socat-smd7-to-ttyIN.service
rm /lib/systemd/system/socat-smd7-from-ttyIN.service
# Reload systemd to apply changes
# Function to install Simple Firewall
install_simple_firewall() {
systemctl stop simplefirewall
systemctl stop ttl-overide
echo -e "\033[0;32mInstalling/Updating Simple Firewall...\033[0m"
mount -o remount,rw /
mkdir -p "$SIMPLE_FIREWALL_DIR"
mkdir -p "$SIMPLE_FIREWALL_SYSTEMD_DIR"
wget -O "$SIMPLE_FIREWALL_DIR/simplefirewall.sh" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/$GITTREE/simplefirewall/simplefirewall.sh
wget -O "$SIMPLE_FIREWALL_DIR/ttl-overide" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/$GITTREE/simplefirewall/ttl-overide
wget -O "$SIMPLE_FIREWALL_DIR/ttlvalue" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/$GITTREE/simplefirewall/ttlvalue
chmod +x "$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
chmod +x "$SIMPLE_FIREWALL_DIR/ttl-overide"
wget -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/simplefirewall.service" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/$GITTREE/simplefirewall/systemd/simplefirewall.service
wget -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/ttl-overide.service" https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/$GITTREE/simplefirewall/systemd/ttl-overide.service
cp -f $SIMPLE_FIREWALL_SYSTEMD_DIR/* /lib/systemd/system
ln -sf "/lib/systemd/system/simplefirewall.service" "/lib/systemd/system/multi-user.target.wants/"
ln -sf "/lib/systemd/system/ttl-overide.service" "/lib/systemd/system/multi-user.target.wants/"
systemctl daemon-reload
# Prompt user before removing micropython
echo "Do you want to remove MicroPython?"
echo "1) Yes"
echo "2) No"
read -p "Enter your choice: " choice
case $choice in
1 )
rm -rf $MICROPYTHON_DIR
echo "MicroPython directory removed."
;;
2 )
echo "MicroPython directory not removed."
;;
* )
echo "Invalid choice. MicroPython directory not removed."
;;
esac
# Remove the AT Telnet Daemon directory
rm -rf $AT_TELNET_DIR
systemctl start simplefirewall
systemctl start ttl-overide
remount_ro
echo "AT Telnet Daemon removed successfully."
echo -e "\033[0;32mSimple Firewall installation/update complete.\033[0m"
}
configure_simple_firewall() {
if [ ! -f "$SIMPLE_FIREWALL_SCRIPT" ]; then
echo "Simple Firewall script not found."
return
fi
echo "Configuring Simple Firewall:"
echo "1) Configure incoming port block"
echo "2) Configure TTL"
read -p "Enter your choice (1-2): " menu_choice
case $menu_choice in
1)
# Original ports configuration code with exit option
current_ports_line=$(grep '^PORTS=' "$SIMPLE_FIREWALL_SCRIPT")
ports=$(echo "$current_ports_line" | cut -d'=' -f2 | tr -d '()' | tr ' ' '\n' | grep -o '[0-9]\+')
echo "Current configured ports:"
echo "$ports" | awk '{print NR") "$0}'
while true; do
echo "Enter a port number to add/remove, or type 'done' or 'exit' to finish:"
read port
if [ "$port" = "done" ] || [ "$port" = "exit" ]; then
if [ "$port" = "exit" ]; then
echo "Exiting without making changes..."
return
fi
break
elif ! echo "$port" | grep -qE '^[0-9]+$'; then
echo "Invalid input: Please enter a numeric value."
elif echo "$ports" | grep -q "^$port\$"; then
ports=$(echo "$ports" | grep -v "^$port\$")
echo "Port $port removed."
else
ports=$(echo "$ports"; echo "$port" | grep -o '[0-9]\+')
echo "Port $port added."
fi
done
if [ "$port" != "exit" ]; then
new_ports_line="PORTS=($(echo "$ports" | tr '\n' ' '))"
sed -i "s/$current_ports_line/$new_ports_line/" "$SIMPLE_FIREWALL_SCRIPT"
fi
;;
2)
# TTL configuration code
ttl_value=$(cat /usrdata/simplefirewall/ttlvalue)
if [ "$ttl_value" -eq 0 ]; then
echo "TTL is not set."
else
echo "TTL value is set to $ttl_value."
fi
echo "Type 'exit' to cancel."
read -p "What do you want the TTL value to be: " new_ttl_value
if [ "$new_ttl_value" = "exit" ]; then
echo "Exiting TTL configuration..."
return
elif ! echo "$new_ttl_value" | grep -qE '^[0-9]+$'; then
echo "Invalid input: Please enter a numeric value."
return
else
echo "$new_ttl_value" > /usrdata/simplefirewall/ttlvalue
echo "TTL value updated to $new_ttl_value."
fi
;;
*)
echo "Invalid choice. Please select either 1 or 2."
;;
esac
systemctl restart simplefirewall
echo "Firewall configuration updated."
}
# Function to install/update Simple Admin
install_update_simple_admin() {
install_simple_admin() {
while true; do
echo "Make sure to Install AT Telnet Daemon first. You don't need to Enable the Telnet Server if you don't need it"
echo "What version of Simple Admin do you want to install? This will start a webserver on port 8080"
echo "What version of Simple Admin do you want to install? This will start a webserver on port 8080"
echo "1) Full Install"
echo "2) No AT Commands, List only (for use with firmware that already has a web UI)"
echo "2) No AT Commands, List only "
echo "3) TTL Only"
echo "4) Install Test Build (work in progress/not ready yet)"
echo "4) Install Test Build (work in progress/not ready yet)"
echo "5) Return to Main Menu"
echo "Select your choice: "
read choice
case $choice in
1)
install_update_at_socat
install_simple_firewall
remount_rw
cd $TMP_DIR
wget $GITHUB_SIMPADMIN_FULL_URL -O simpleadminfull.zip
unzip -o simpleadminfull.zip
cp -Rf quectel-rgmii-toolkit-simpleadminfull/simpleadmin/ $USRDATA_DIR
chmod +x $SIMPLE_ADMIN_DIR/scripts/*
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
chmod +x $SIMPLE_ADMIN_DIR/ttl/ttl-override
cp -f $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
systemctl daemon-reload
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
ln -sf /lib/systemd/system/simpleadmin_generate_status.service /lib/systemd/system/multi-user.target.wants/
ln -sf /lib/systemd/system/ttl-override.service /lib/systemd/system/multi-user.target.wants/
systemctl start simpleadmin_generate_status
systemctl start simpleadmin_httpd
systemctl start ttl-override
remount_ro
echo "Cleaning up..."
rm /tmp/simpleadminfull.zip
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminfull/
break
;;
2)
install_update_at_socat
install_simple_firewall
remount_rw
cd $TMP_DIR
wget $GITHUB_SIMPADMIN_NOCMD_URL -O simpleadminnoatcmds.zip
unzip -o simpleadminnoatcmds.zip
cp -Rf quectel-rgmii-toolkit-simpleadminnoatcmds/simpleadmin/ $USRDATA_DIR
chmod +x $SIMPLE_ADMIN_DIR/scripts/*
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
chmod +x $SIMPLE_ADMIN_DIR/ttl/ttl-override
cp -f $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
systemctl daemon-reload
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
ln -sf /lib/systemd/system/simpleadmin_generate_status.service /lib/systemd/system/multi-user.target.wants/
ln -sf /lib/systemd/system/ttl-override.service /lib/systemd/system/multi-user.target.wants/
systemctl start simpleadmin_generate_status
systemctl start simpleadmin_httpd
systemctl start ttl-override
remount_ro
echo "Cleaning up..."
rm /tmp/simpleadminnoatcmds.zip
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminnoatcmds/
echo "Cleaning up..."
rm /tmp/simpleadminnoatcmds.zip
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminnoatcmds/
break
;;
3)
install_simple_firewall
remount_rw
cd $TMP_DIR
wget $GITHUB_SIMPADMIN_TTL_URL -O simpleadminttlonly.zip
unzip -o simpleadminttlonly.zip
cp -Rf quectel-rgmii-toolkit-simpleadminttlonly/simpleadmin/ $USRDATA_DIR
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
chmod +x $SIMPLE_ADMIN_DIR/ttl/ttl-override
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
cp -f $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
systemctl daemon-reload
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
ln -sf /lib/systemd/system/ttl-override.service /lib/systemd/system/multi-user.target.wants/
systemctl start simpleadmin_httpd
systemctl start ttl-override
remount_ro
echo "Cleaning up..."
rm /tmp/simpleadminttlonly.zip
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminttlonly/
echo "Cleaning up..."
rm /tmp/simpleadminttlonly.zip
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminttlonly/
break
;;
4)
remount_rw
install_update_at_socat
install_simple_firewall
remount_rw
cd $TMP_DIR
wget $GITHUB_SIMPADMIN_TEST_URL -O simpleadmintest.zip
wget $GITHUB_SIMPADMIN_FULL_URL -O simpleadmintest.zip
unzip -o simpleadmintest.zip
cp -Rf quectel-rgmii-toolkit-simpleadmintest/simpleadmin/ $USRDATA_DIR
chmod +x $SIMPLE_ADMIN_DIR/scripts/*
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
chmod +x $SIMPLE_ADMIN_DIR/ttl/ttl-override
cp -f $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
systemctl daemon-reload
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
ln -sf /lib/systemd/system/simpleadmin_generate_status.service /lib/systemd/system/multi-user.target.wants/
ln -sf /lib/systemd/system/ttl-override.service /lib/systemd/system/multi-user.target.wants/
systemctl start simpleadmin_generate_status
systemctl start simpleadmin_httpd
systemctl start ttl-override
remount_ro
break
;;
@@ -525,23 +388,70 @@ install_update_simple_admin() {
done
}
# Function to Uninstall Simpleadmin and dependencies
uninstall_simpleadmin_components() {
echo "Starting the uninstallation process for Simpleadmin components."
echo "Note: Uninstalling certain components may affect the functionality of others."
# Uninstall Simple Firewall
echo "Do you want to uninstall Simplefirewall?"
echo "If you do, the TTL part of simpleadmin will no longer work."
echo "1) Yes"
echo "2) No"
read -p "Enter your choice (1 or 2): " choice_simplefirewall
if [ "$choice_simplefirewall" -eq 1 ]; then
echo "Uninstalling Simplefirewall..."
systemctl stop simplefirewall
systemctl stop ttl-overide
rm -f /lib/systemd/system/simplefirewall.service
rm -f /lib/systemd/system/ttl-overide.service
systemctl daemon-reload
rm -rf "$SIMPLE_FIREWALL_DIR"
echo "Simplefirewall uninstalled."
fi
# Function to remove Simple Admin
remove_simple_admin() {
remount_rw
systemctl stop simpleadmin_generate_status
systemctl stop ttl-override
systemctl stop simpleadmin_httpd
systemctl disable simpleadmin_httpd
systemctl disable ttl-override
systemctl disable simpleadmin_httpd
rm -rf $SIMPLE_ADMIN_DIR
rm /lib/systemd/system/simpleadmin_httpd.service
rm /lib/systemd/system/simpleadmin_generate_status.service
rm /lib/systemd/system/ttl-override.service
systemctl daemon-reload
remount_ro
# Uninstall socat-at-bridge
echo "Do you want to uninstall socat-at-bridge?"
echo "If you do, AT commands and the stat page will no longer work."
echo "1) Yes"
echo "2) No"
read -p "Enter your choice (1 or 2): " choice_socat_at_bridge
if [ "$choice_socat_at_bridge" -eq 1 ]; then
echo "Uninstalling socat-at-bridge..."
systemctl stop socat-smd11
systemctl stop socat-smd11-to-ttyIN
systemctl stop socat-smd11-from-ttyIN
systemctl stop socat-smd7
systemctl stop socat-smd7-to-ttyIN
systemctl stop socat-smd7-from-ttyIN
rm -f /lib/systemd/system/socat-smd11.service
rm -f /lib/systemd/system/socat-smd11-to-ttyIN.service
rm -f /lib/systemd/system/socat-smd11-from-ttyIN.service
rm -f /lib/systemd/system/socat-smd7.service
rm -f /lib/systemd/system/socat-smd7-to-ttyIN.service
rm -f /lib/systemd/system/socat-smd7-from-ttyIN.service
systemctl daemon-reload
rm -rf "$SOCAT_AT_DIR"
echo "socat-at-bridge uninstalled."
fi
# Uninstall the rest of Simpleadmin
echo "Do you want to uninstall the rest of Simpleadmin?"
echo "1) Yes"
echo "2) No"
read -p "Enter your choice (1 or 2): " choice_simpleadmin
if [ "$choice_simpleadmin" -eq 1 ]; then
echo "Uninstalling the rest of Simpleadmin..."
systemctl stop simpleadmin_httpd
systemctl stop simpleadmin_generate_status
rm -f /lib/systemd/system/simpleadmin_httpd.service
rm -f /lib/systemd/system/simpleadmin_generate_status.service
systemctl daemon-reload
rm -rf "$SIMPLE_ADMIN_DIR"
echo "The rest of Simpleadmin uninstalled."
fi
echo "Uninstallation process completed."
}
# Function for Tailscale Submenu
@@ -572,41 +482,12 @@ install_update_remove_tailscale() {
case $tailscale_update_remove_choice in
1)
echo "Updating Tailscale..."
remount_rw
$TAILSCALE_DIR/tailscale down
$TAILSCALE_DIR/tailscale logout
systemctl stop tailscaled
# Follow the installation steps with force overwrite
echo "Downloading the latest Tailscale binaries..."
wget -O $TAILSCALE_DIR/tailscaled https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/tailscaled
wget -O $TAILSCALE_DIR/tailscale https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/tailscale
echo "Setting permissions for the new binaries..."
chmod +x $TAILSCALE_DIR/tailscaled
chmod +x $TAILSCALE_DIR/tailscale
echo "Downloading the latest systemd files..."
wget -O $TAILSCALE_SYSD_DIR/tailscaled.service https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/systemd/tailscaled.service
wget -O $TAILSCALE_SYSD_DIR/tailscaled.defaults https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/systemd/tailscaled.defaults
echo "Copying the new systemd units..."
cp -f $TAILSCALE_SYSD_DIR/* /lib/systemd/system
systemctl daemon-reload
echo "Restarting Tailscaled service..."
systemctl restart tailscaled
echo "Tailscale updated successfully."
remount_ro
echo "Tailscale updated successfully."
echo "You will need to reconnect and Log back in"
read -p "Press Enter to continue..."
echo "Updating Tailscale..."
/usrdata/tailscale/tailscale update
;;
2)
echo "Removing Tailscale..."
remount_rw
remount_rw
$TAILSCALE_DIR/tailscale down
$TAILSCALE_DIR/tailscale logout
systemctl stop tailscaled
@@ -623,82 +504,81 @@ install_update_remove_tailscale() {
else
echo "Installing Tailscale..."
remount_rw
echo "Creating /usrdata/tailscale/"
mkdir $TAILSCALE_DIR
mkdir $TAILSCALE_SYSD_DIR
echo "Creating /usrdata/tailscale/"
mkdir $TAILSCALE_DIR
mkdir $TAILSCALE_SYSD_DIR
cd $TAILSCALE_DIR
echo "Downloading binary: /usrdata/tailscale/tailscaled"
echo "Downloading binary: /usrdata/tailscale/tailscaled"
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/tailscaled
echo "Downloading binary: /usrdata/tailscale/tailscale"
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/tailscale
echo "Downloading binary: /usrdata/tailscale/tailscale"
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/tailscale
echo "Downloading systemd files..."
cd $TAILSCALE_SYSD_DIR
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/systemd/tailscaled.service
wget https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/systemd/tailscaled.defaults
sleep 2s
echo "Setting Permissions..."
sleep 2s
echo "Setting Permissions..."
chmod +x /usrdata/tailscale/tailscaled
chmod +x /usrdata/tailscale/tailscale
echo "Copy systemd units..."
echo "Copy systemd units..."
cp -f /usrdata/tailscale/systemd/* /lib/systemd/system
ln -sf /lib/systemd/system/tailscaled.service /lib/systemd/system/multi-user.target.wants/
ln -sf /lib/systemd/system/tailscaled.service /lib/systemd/system/multi-user.target.wants/
systemctl daemon-reload
echo "Starting Tailscaled..."
echo "Starting Tailscaled..."
systemctl start tailscaled
cd /
cd /
remount_ro
echo "Tailscale installed successfully."
fi
}
# Function to Configure Tailscale
configure_tailscale() {
while true; do
echo "Configure Tailscale"
echo "1) Enable Tailscale Web UI at http://192.168.225.1:8088 (Gateway on port 8088)"
echo "Configure Tailscale"
echo "1) Enable Tailscale Web UI at http://192.168.225.1:8088 (Gateway on port 8088)"
echo "2) Disable Tailscale Web UI"
echo "3) Connect to Tailnet"
echo "4) Connect to Tailnet with SSH ON"
echo "5) Connect to Tailnet with SSH OFF (reset flag)"
echo "4) Connect to Tailnet with SSH ON"
echo "5) Reconnect to Tailnet with SSH OFF"
echo "6) Disconnect from Tailnet (reconnects at reboot)"
echo "7) Logout from tailscale account"
echo "7) Logout from tailscale account"
echo "8) Return to Tailscale Menu"
read -p "Enter your choice: " config_choice
case $config_choice in
1)
1)
remount_rw
cd /lib/systemd/system/
wget -O tailscale-webui.service https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/systemd/tailscale-webui.service
wget -O tailscale-webui-trigger.service https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/tailscale/systemd/tailscale-webui-trigger.service
ln -sf /lib/systemd/system/tailscale-webui-trigger.service /lib/systemd/system/multi-user.target.wants/
systemctl daemon-reload
echo "Tailscale Web UI Enabled"
ln -sf /lib/systemd/system/tailscale-webui-trigger.service /lib/systemd/system/multi-user.target.wants/
systemctl daemon-reload
echo "Tailscale Web UI Enabled"
echo "Starting Web UI..."
systemctl start tailscale-webui
echo "Web UI started!"
remount_ro
systemctl start tailscale-webui
echo "Web UI started!"
remount_ro
;;
2)
remount_rw
systemctl stop tailscale-webui
systemctl disable tailscale-webui-trigger
systemctl disable tailscale-webui-trigger
rm /lib/systemd/system/multi-user.target.wants/tailscale-webui.service
rm /lib/systemd/system/multi-user.target.wants/tailscale-webui-trigger.service
rm /lib/systemd/system/tailscale-webui.service
rm /lib/systemd/system/tailscale-webui-trigger.service
systemctl daemon-reload
echo "Tailscale Web UI Stopped and Disabled"
remount_ro
rm /lib/systemd/system/multi-user.target.wants/tailscale-webui-trigger.service
rm /lib/systemd/system/tailscale-webui.service
rm /lib/systemd/system/tailscale-webui-trigger.service
systemctl daemon-reload
echo "Tailscale Web UI Stopped and Disabled"
remount_ro
;;
3) $TAILSCALE_DIR/tailscale up;;
4) $TAILSCALE_DIR/tailscale up --ssh;;
5) $TAILSCALE_DIR/tailscale up --reset;;
6) $TAILSCALE_DIR/tailscale down;;
7) $TAILSCALE_DIR/tailscale logout;;
8) break;;
*) echo "Invalid option";;
3) $TAILSCALE_DIR/tailscale up --accept-dns=false --reset;;
4) $TAILSCALE_DIR/tailscale up --ssh --accept-dns=false --reset;;
5) $TAILSCALE_DIR/tailscale up --accept-dns=false --reset;;
6) $TAILSCALE_DIR/tailscale down;;
7) $TAILSCALE_DIR/tailscale logout;;
8) break;;
*) echo "Invalid option";;
esac
done
}
@@ -773,7 +653,7 @@ manage_reboot_timer() {
mount -o remount,ro /
}
# Function to create systemd service and timer files with the user-specified time
# Function to create systemd service and timer files with the user-specified time for the reboot timer
create_service_and_timer() {
remount_rw
# Define the path for the modem reboot script
@@ -880,20 +760,17 @@ WantedBy=multi-user.target" > "$cfun_service_path"
fi
}
# Main menu
while true; do
echo "Welcome to iamromulan's RGMII Toolkit script for Quectel RMxxx Series modems!"
echo "Select an option:"
echo "1) Send AT Commands"
echo "2) Install/Update/Uninstall or Configure Simple Firewall"
echo "3) Install/Update or remove AT Telnet Daemon"
echo "4) Install/Update or remove Simple Admin"
echo "5) Tailscale Management"
echo "6) Install/Change or remove Daily Reboot Timer"
echo "7) Install/Uninstall CFUN 0 Fix"
echo "8) Exit"
echo "2) Install/Update/Uninstall Simple Admin"
echo "3) Simple Firewall Management"
echo "4) Tailscale Management"
echo "5) Install/Change or remove Daily Reboot Timer"
echo "6) Install/Uninstall CFUN 0 Fix"
echo "7) Exit"
read -p "Enter your choice: " choice
case $choice in
@@ -901,53 +778,38 @@ while true; do
send_at_commands
;;
2)
simplefirewall_menu
;;
3)
if is_at_telnet_installed; then
echo "AT Telnet Daemon is already installed."
echo "1) Update"
echo "2) Remove"
read -p "Enter your choice: " at_telnet_choice
case $at_telnet_choice in
1) install_update_at_telnet;;
2) remove_at_telnet;;
*) echo "Invalid option";;
esac
else
echo "Installing AT Telnet Daemon..."
install_update_at_telnet
fi
;;
4)
if is_simple_admin_installed; then
echo "Simple Admin is already installed."
echo "1) Update"
echo "2) Remove"
echo "Simple Admin is already installed. It must be removed first"
echo "1) Remove"
echo "2) Return to main menu"
read -p "Enter your choice: " simple_admin_choice
case $simple_admin_choice in
1) install_update_simple_admin;;
2) remove_simple_admin;;
1) uninstall_simpleadmin_components;;
2) break;;
*) echo "Invalid option";;
esac
else
echo "Installing Simple Admin..."
install_update_simple_admin
install_simple_admin
fi
;;
5)
tailscale_menu
;;
6)
3)
configure_simple_firewall
;;
4)
tailscale_menu
;;
5)
manage_reboot_timer
;;
7)
6)
manage_cfun_fix
;;
8)
echo "Goodbye!"
7)
echo "Goodbye!"
break
;;
;;
*)
echo "Invalid option"
;;

View File

@@ -1,281 +0,0 @@
#!/usrdata/micropython/micropython
# Add the /usrdata/micropython directory to sys.path so we can find the external modules.
# TODO: Move external modules to lib?
# TODO: Recompile Micropython with a syspath set up for our use case.
import sys
# Remove the home directory from sys.path.
if "~/.micropython/lib" in sys.path:
sys.path.remove("~/.micropython/lib")
sys.path.append("/usrdata/micropython/lib")
sys.path.append("/usrdata/micropython")
import uos
import usocket as socket
import _thread as thread
import serial
import select
import traceback
import logging
import re
import time
# Set up logging
logging.basicConfig(level=logging.INFO, format='[%(asctime)s: %(levelname)s/%(msecs)ims] %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
# Globally define client_sockets and serialport. That way, we can access them from handle_output and make it a separate thread, so responses (and unsolicited responses) can come in while we're waiting for input.
global client_sockets, serialport
client_sockets = []
# We are referencing one of the two ports exposed by our socat command. The other one is /dev/ttyIN, and two running "cat" commands are keeping it sync'd with /dev/smd11.
serialport = serial.Serial("/dev/ttyOUT", baudrate=115200)
# These will be set in the main routine.
global firewall_is_setup, fwpublicinterface, port
firewall_is_setup = 0
# Make these configurable via /etc/default or similar
port = 5000
fwpublicinterface = "rmnet+"
# Block access to port 5000 via ipv4 and ipv6 on public-facing interfaces.
def add_firewll_rules(port=port, fwpublicinterface=fwpublicinterface):
if not port or not fwpublicinterface:
logging.error(f"Port or fwpublicinterface not set. Values: fwpublicinterface: {fwpublicinterface} port: {port}")
exit(1)
logging.info(f"Adding firewall rules for port {port} on interface {fwpublicinterface}.")
# Check if the rule already exists in iptables
iptables_check_cmd = f"iptables -C INPUT -i {fwpublicinterface} -p tcp --dport {port} -j REJECT &> /dev/null"
iptables_check_result = uos.system(iptables_check_cmd)
if iptables_check_result != 0:
# Rule doesn't exist, add it to iptables
iptables_add_cmd = f"iptables -A INPUT -i {fwpublicinterface} -p tcp --dport {port} -j REJECT"
iptables_add_result = uos.system(iptables_add_cmd)
if iptables_add_result:
logging.error(f"ERROR: Failed to add iptables rule - input interface {fwpublicinterface} port {port}")
# Treat this as fatal.
sys.exit(1)
else:
logging.debug(f"Added iptables rule - input interface {fwpublicinterface} port {port}")
# Check if the rule already exists in ip6tables
ip6tables_check_cmd = f"ip6tables -C INPUT -i {fwpublicinterface} -p tcp --dport {port} -j REJECT &> /dev/null"
ip6tables_check_result = uos.system(ip6tables_check_cmd)
if ip6tables_check_result != 0:
# Rule doesn't exist, add it to ip6tables
ip6tables_add_cmd = f"ip6tables -A INPUT -i {fwpublicinterface} -p tcp --dport {port} -j REJECT"
ip6tables_add_result = uos.system(ip6tables_add_cmd)
if ip6tables_add_result:
logging.error(f"ERROR: Failed to add ip6tables rule - input interface {fwpublicinterface} port {port}")
# Treat this as fatal.
sys.exit(1)
else:
logging.debug(f"Added ip6tables rule - input interface {fwpublicinterface} port {port}")
global firewall_is_setup
firewall_is_setup = 1
logging.info(f"Successfully firewall rules for port {port} on interface {fwpublicinterface}.")
def remove_firewall_rules(port=port, fwpublicinterface=fwpublicinterface):
if firewall_is_setup:
iptables_del_cmd = f"iptables -D INPUT -i {fwpublicinterface} -p tcp --dport {port} -j REJECT"
ip6tables_del_cmd = f"ip6tables -D INPUT -i {fwpublicinterface} -p tcp --dport {port} -j REJECT"
iptables_del_result = uos.system(iptables_del_cmd)
ip6tables_del_result = uos.system(ip6tables_del_cmd)
if iptables_del_result or ip6tables_del_result:
logging.error(f"ERROR: Failed to remove iptables or ip6tables rule - input interface {fwpublicinterface} port {port}")
else:
logging.info(f"Removed iptables and ip6tables rule - input interface {fwpublicinterface} port {port}")
else:
logging.info(f"Firewall rules not set up; not removing.")
# This routine pulls data from the serial port and sends it to all connected clients.
def handle_output():
while True:
# Make data an empty bytes list
data = b''
try:
while serialport.in_waiting > 0:
data += serialport.read(1)
except Exception as e:
# This will keep trying.
print(f"Exception reading data from serialport: {e}")
traceback.print_exc()
if data:
logging.info(f"Got data from modem: {data}")
for client_socket in client_sockets:
client_socket.send(data)
# Start the server on the specified port, listen for clients, etc.
def start_at_server(port):
# Server initialization stuff
# NOTE: This now supports IPv6. And means that on many connections it'll be directly exposed
# to the internet. So we're adding firewall rules to block access to it via rmnet+.
try:
server_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
addr_info = socket.getaddrinfo("::", port)
addr = addr_info[0][4]
server_socket.bind(addr)
server_socket.listen(1)
logging.info(f"AT Server listening on TCP port {port}")
# Disable echo so user doesn't see a second copy of all their commands.
serialport.write("ATE0\r\n")
# time.sleep() segfaults?! ugh.
uos.system("sleep 0.025s")
# wait for an OK
out=b''
while serialport.in_waiting > 0:
out += serialport.read(1)
if "OK" not in str(out):
logging.warning(f"Did not get expected OK when running ATE0. Result: {str(out)}")
except Exception as e:
logging.error(f"Error initializing server: {e}")
traceback.print_exc()
raise
# Start the output handler in its own thread
try:
thread.start_new_thread(handle_output, ())
except Exception as e:
print("Error with output handler:", e)
traceback.print_exc()
raise
# Set up a select.poll object to listen for input from the server socket and all client sockets.
# Logic mostly from https://pymotw.com/2/select/
try:
poll_obj = select.poll()
poll_obj.register(server_socket, select.POLLIN)
# Register the server socket in the fd_to_socket dict; this will also be used to register the rest of the clients.
fd_to_socket = { server_socket.fileno(): server_socket,
}
while True:
events = poll_obj.poll()
for fd, flag in events:
logging.debug(f"Pool loop event. fd: {fd} flag: {flag} fd_to_socket.keys(): {fd_to_socket.keys()}")
# Check if the client already exists in the fd_to_socket dict.
if fd.fileno() in fd_to_socket.keys():
s = fd_to_socket[fd.fileno()]
logging.debug("Event matches existing socket.")
else:
s = fd
logging.debug(f"Event doesn't match existing socket. fd: {fd} fd_to_socket: {fd_to_socket}")
# If the flag is POLLIN, then we have data to process.
if flag & (select.POLLIN):
# If the server socket is ready to read, then we have a new client connection.
if s is server_socket:
# Accept the connection.
client_socket, client_address = s.accept()
# TODO: This gives a garbled IP. Figure it out.
#client_address_translated = socket.inet_ntop(socket.AF_INET, client_address)
logging.info(f"New connection")
# Set the client socket to non-blocking, and add it to the list of client sockets.
# TODO: trim down to just storing one copy of the client sockets..
client_socket.setblocking(0)
fd_to_socket[ client_socket.fileno() ] = client_socket
client_sockets.append(client_socket)
poll_obj.register(client_socket, select.POLLIN)
# Send a good 'ol hello message to the client.
client_socket.send("** Welcome to the AT server!\r\n".encode())
client_socket.send("** Note that your commands are interleaved with any other connected clients,\r\n** so responses may appear out of order.\r\n".encode())
client_socket.send("** \r\n".encode())
client_socket.send("** You may also receive unsolicited responses (URC's) depending on the\r\n** modem configuration.\r\n".encode())
client_socket.send("** \r\n".encode())
client_socket.send("** Echo is off (ATE0); if you change it you'll see what you've typed both\r\n** locally and echo'd back.\r\n".encode())
client_socket.send("** \r\n".encode())
client_socket.send("** I have tested this with telnet.netkit and netcat on Linux. If your client\r\n** doesn't work,\r\n** please open an issue at:\r\n** https://github.com/natecarlson/quectel-rgmii-at-command-client/ **\r\n".encode())
client_socket.send("**\r\n".encode())
client_socket.send("** If you would like to support further development, you can at:\r\n** https://www.buymeacoffee.com/natecarlson **\r\n".encode())
client_socket.send("\r\n".encode())
# Otherwise, we have data from a client socket.
else:
data = s.recv(1024)
logging.info(f"Got data from client: {data}")
if data:
# Ensure it ends with \r\n
if not data.endswith("\r\n"):
# Just stripping \n for now; add others in the future if needed.
data = re.sub(b"\n$", "", data) + "\r\n"
logging.info(f"Modified client data to end with \\r\\n: {data}")
# Good client data; write out to the serial port.
serialport.write(data)
# Write out out to the rest of the clients too
for fd in fd_to_socket.keys():
if fd != server_socket.fileno() and fd != s.fileno():
logging.debug(f"Writing data to other connected client: {data}")
try:
fd_to_socket[fd].send(data)
except Exception as e:
logging.info(f"Failed to write data to an additional client. Ignorning. Result: {e}")
pass
else:
# Client disconnected
print("Client disconnected")
client_sockets.remove(s)
poll_obj.unregister(s)
del fd_to_socket[s.fileno()]
s.close()
# Not sure if this can happen. But , if it does, we should close the socket.
elif flag & select.POLLERR:
logging.warn(f"Strange connection issue with a client; closing.")
# Stop listening for input on the connection
poll_obj.unregister(s)
client_sockets.remove(s)
del fd_to_socket[s.fileno()]
s.close()
# TODO: I don't believe we need this here, since the output is now handled in its own thread.
#uos.system("sleep 0.025s")
except Exception as e:
print("Error after server initialization:", e)
serialport.write("ATE1\r\n")
traceback.print_exc()
# I believe this will drop out of the while loop, so we'll close the sockets and exit.
# Close client sockets and server socket
for client_socket in client_sockets:
client_socket.close()
server_socket.close()
# TODO: By using the dict, we shouldn't need this code. Clean it up.
#def fd_to_socket(fd, client_sockets):
# for client_socket in client_sockets:
# if client_socket.fileno() == fd:
# return client_socket
# return None
# App startup. TODO: Make the port configurable.
if __name__ == "__main__":
# Register an atexit handler to remove the firewall rules.
sys.atexit(remove_firewall_rules)
# Add the firewall rules before starting anything
add_firewll_rules(port=port, fwpublicinterface=fwpublicinterface)
# Light 'er up!
start_at_server(port)

Binary file not shown.

View File

@@ -1,21 +0,0 @@
[Unit]
Description=Telnet daemon for AT command smd7
After=socat-smd7.service
Requires=socat-smd7.service socat-smd7-from-ttyIN.service socat-smd7-to-ttyIN.service
ReloadPropagatedFrom=socat-smd7.service socat-smd7-from-ttyIN.service socat-smd7-to-ttyIN.service
StartLimitIntervalSec=2m
StartLimitBurst=100
[Service]
ExecStart=/usrdata/at-telnet/modem-multiclient.py
Nice=5
Restart=always
RestartSec=2s
# Increased log rate limits, so we can see what's going on.
LogRateLimitIntervalSec=5s
LogRateLimitBurst=100
[Install]
WantedBy=multi-user.target

View File

@@ -1,25 +0,0 @@
[Unit]
Description=Telnet daemon for AT command
# Being extra silly with the dependencies for this.
# TODO: Update the python code to validate that the serial port
# is working on a regular basis, and keep attempting to retry
# if not. Then these dependencies won't need to be so strict.
After=socat-smd11.service
Requires=socat-smd11.service socat-smd11-from-ttyIN.service socat-smd11-to-ttyIN.service
ReloadPropagatedFrom=socat-smd11.service socat-smd11-from-ttyIN.service socat-smd11-to-ttyIN.service
StartLimitIntervalSec=2m
StartLimitBurst=100
[Service]
ExecStart=/usrdata/at-telnet/modem-multiclient.py
Nice=5
Restart=always
RestartSec=2s
# Increased log rate limits, so we can see what's going on.
LogRateLimitIntervalSec=5s
LogRateLimitBurst=100
[Install]
WantedBy=multi-user.target

View File

@@ -1,38 +0,0 @@
EPERM = 1 # Operation not permitted
ENOENT = 2 # No such file or directory
ESRCH = 3 # No such process
EINTR = 4 # Interrupted system call
EIO = 5 # I/O error
ENXIO = 6 # No such device or address
E2BIG = 7 # Argument list too long
ENOEXEC = 8 # Exec format error
EBADF = 9 # Bad file number
ECHILD = 10 # No child processes
EAGAIN = 11 # Try again
ENOMEM = 12 # Out of memory
EACCES = 13 # Permission denied
EFAULT = 14 # Bad address
ENOTBLK = 15 # Block device required
EBUSY = 16 # Device or resource busy
EEXIST = 17 # File exists
EXDEV = 18 # Cross-device link
ENODEV = 19 # No such device
ENOTDIR = 20 # Not a directory
EISDIR = 21 # Is a directory
EINVAL = 22 # Invalid argument
ENFILE = 23 # File table overflow
EMFILE = 24 # Too many open files
ENOTTY = 25 # Not a typewriter
ETXTBSY = 26 # Text file busy
EFBIG = 27 # File too large
ENOSPC = 28 # No space left on device
ESPIPE = 29 # Illegal seek
EROFS = 30 # Read-only file system
EMLINK = 31 # Too many links
EPIPE = 32 # Broken pipe
EDOM = 33 # Math argument out of domain of func
ERANGE = 34 # Math result not representable
EAFNOSUPPORT = 97 # Address family not supported by protocol
ECONNRESET = 104 # Connection timed out
ETIMEDOUT = 110 # Connection timed out
EINPROGRESS = 115 # Operation now in progress

View File

@@ -1,36 +0,0 @@
import ffi
import os_compat as os
import ffilib
libc = ffilib.libc()
fcntl_l = libc.func("i", "fcntl", "iil")
fcntl_s = libc.func("i", "fcntl", "iip")
ioctl_l = libc.func("i", "ioctl", "iil")
ioctl_s = libc.func("i", "ioctl", "iip")
def fcntl(fd, op, arg=0):
if type(arg) is int:
r = fcntl_l(fd, op, arg)
os.check_error(r)
return r
else:
r = fcntl_s(fd, op, arg)
os.check_error(r)
# TODO: Not compliant. CPython says that arg should be immutable,
# and possibly mutated buffer is returned.
return r
def ioctl(fd, op, arg=0, mut=False):
if type(arg) is int:
r = ioctl_l(fd, op, arg)
os.check_error(r)
return r
else:
# TODO
assert mut
r = ioctl_s(fd, op, arg)
os.check_error(r)
return r

View File

@@ -1,51 +0,0 @@
import sys
try:
import ffi
except ImportError:
ffi = None
_cache = {}
def open(name, maxver=10, extra=()):
if not ffi:
return None
try:
return _cache[name]
except KeyError:
pass
def libs():
if sys.platform == "linux":
yield '%s.so' % name
for i in range(maxver, -1, -1):
yield '%s.so.%u' % (name, i)
else:
for ext in ('dylib', 'dll'):
yield '%s.%s' % (name, ext)
for n in extra:
yield n
err = None
for n in libs():
try:
l = ffi.open(n)
_cache[name] = l
return l
except OSError as e:
err = e
raise err
def libc():
return open("libc", 6)
# Find out bitness of the platform, even if long ints are not supported
# TODO: All bitness differences should be removed from micropython-lib, and
# this snippet too.
bitness = 1
v = sys.maxsize
while v:
bitness += 1
v >>= 1

View File

@@ -1,245 +0,0 @@
from micropython import const
import sys
import time
CRITICAL = const(50)
ERROR = const(40)
WARNING = const(30)
INFO = const(20)
DEBUG = const(10)
NOTSET = const(0)
_DEFAULT_LEVEL = const(WARNING)
_level_dict = {
CRITICAL: "CRITICAL",
ERROR: "ERROR",
WARNING: "WARNING",
INFO: "INFO",
DEBUG: "DEBUG",
NOTSET: "NOTSET",
}
_loggers = {}
_stream = sys.stderr
_default_fmt = "%(levelname)s:%(name)s:%(message)s"
_default_datefmt = "%Y-%m-%d %H:%M:%S"
class LogRecord:
def set(self, name, level, message):
self.name = name
self.levelno = level
self.levelname = _level_dict[level]
self.message = message
self.ct = time.time()
self.msecs = int((self.ct - int(self.ct)) * 1000)
self.asctime = None
class Handler:
def __init__(self, level=NOTSET):
self.level = level
self.formatter = None
def close(self):
pass
def setLevel(self, level):
self.level = level
def setFormatter(self, formatter):
self.formatter = formatter
def format(self, record):
return self.formatter.format(record)
class StreamHandler(Handler):
def __init__(self, stream=None):
self.stream = _stream if stream is None else stream
self.terminator = "\n"
def close(self):
if hasattr(self.stream, "flush"):
self.stream.flush()
def emit(self, record):
if record.levelno >= self.level:
self.stream.write(self.format(record) + self.terminator)
class FileHandler(StreamHandler):
def __init__(self, filename, mode="a", encoding="UTF-8"):
super().__init__(stream=open(filename, mode=mode, encoding=encoding))
def close(self):
super().close()
self.stream.close()
class Formatter:
def __init__(self, fmt=None, datefmt=None):
self.fmt = _default_fmt if fmt is None else fmt
self.datefmt = _default_datefmt if datefmt is None else datefmt
def usesTime(self):
return "asctime" in self.fmt
def formatTime(self, datefmt, record):
if hasattr(time, "strftime"):
return time.strftime(datefmt, time.localtime(record.ct))
return None
def format(self, record):
if self.usesTime():
record.asctime = self.formatTime(self.datefmt, record)
return self.fmt % {
"name": record.name,
"message": record.message,
"msecs": record.msecs,
"asctime": record.asctime,
"levelname": record.levelname,
}
class Logger:
def __init__(self, name, level=NOTSET):
self.name = name
self.level = level
self.handlers = []
self.record = LogRecord()
def setLevel(self, level):
self.level = level
def isEnabledFor(self, level):
return level >= self.getEffectiveLevel()
def getEffectiveLevel(self):
return self.level or getLogger().level or _DEFAULT_LEVEL
def log(self, level, msg, *args):
if self.isEnabledFor(level):
if args:
if isinstance(args[0], dict):
args = args[0]
msg = msg % args
self.record.set(self.name, level, msg)
handlers = self.handlers
if not handlers:
handlers = getLogger().handlers
for h in handlers:
h.emit(self.record)
def debug(self, msg, *args):
self.log(DEBUG, msg, *args)
def info(self, msg, *args):
self.log(INFO, msg, *args)
def warning(self, msg, *args):
self.log(WARNING, msg, *args)
def error(self, msg, *args):
self.log(ERROR, msg, *args)
def critical(self, msg, *args):
self.log(CRITICAL, msg, *args)
def exception(self, msg, *args):
self.log(ERROR, msg, *args)
if hasattr(sys, "exc_info"):
sys.print_exception(sys.exc_info()[1], _stream)
def addHandler(self, handler):
self.handlers.append(handler)
def hasHandlers(self):
return len(self.handlers) > 0
def getLogger(name=None):
if name is None:
name = "root"
if name not in _loggers:
_loggers[name] = Logger(name)
if name == "root":
basicConfig()
return _loggers[name]
def log(level, msg, *args):
getLogger().log(level, msg, *args)
def debug(msg, *args):
getLogger().debug(msg, *args)
def info(msg, *args):
getLogger().info(msg, *args)
def warning(msg, *args):
getLogger().warning(msg, *args)
def error(msg, *args):
getLogger().error(msg, *args)
def critical(msg, *args):
getLogger().critical(msg, *args)
def exception(msg, *args):
getLogger().exception(msg, *args)
def shutdown():
for k, logger in _loggers.items():
for h in logger.handlers:
h.close()
_loggers.pop(logger, None)
def addLevelName(level, name):
_level_dict[level] = name
def basicConfig(
filename=None,
filemode="a",
format=None,
datefmt=None,
level=WARNING,
stream=None,
encoding="UTF-8",
force=False,
):
if "root" not in _loggers:
_loggers["root"] = Logger("root")
logger = _loggers["root"]
if force or not logger.handlers:
for h in logger.handlers:
h.close()
logger.handlers = []
if filename is None:
handler = StreamHandler(stream)
else:
handler = FileHandler(filename, filemode, encoding)
handler.setLevel(level)
handler.setFormatter(Formatter(format, datefmt))
logger.setLevel(level)
logger.addHandler(handler)
if hasattr(sys, "atexit"):
sys.atexit(shutdown)

View File

@@ -1,312 +0,0 @@
import array
import ustruct as struct
import errno as errno_
import stat as stat_
import ffilib
import uos
from micropython import const
R_OK = const(4)
W_OK = const(2)
X_OK = const(1)
F_OK = const(0)
O_ACCMODE = 0o0000003
O_RDONLY = 0o0000000
O_WRONLY = 0o0000001
O_RDWR = 0o0000002
O_CREAT = 0o0000100
O_EXCL = 0o0000200
O_NOCTTY = 0o0000400
O_TRUNC = 0o0001000
O_APPEND = 0o0002000
O_NONBLOCK = 0o0004000
error = OSError
name = "posix"
sep = "/"
curdir = "."
pardir = ".."
environ = {"WARNING": "NOT_IMPLEMENTED"}
libc = ffilib.libc()
if libc:
chdir_ = libc.func("i", "chdir", "s")
mkdir_ = libc.func("i", "mkdir", "si")
rename_ = libc.func("i", "rename", "ss")
unlink_ = libc.func("i", "unlink", "s")
rmdir_ = libc.func("i", "rmdir", "s")
getcwd_ = libc.func("s", "getcwd", "si")
opendir_ = libc.func("P", "opendir", "s")
readdir_ = libc.func("P", "readdir", "P")
open_ = libc.func("i", "open", "sii")
read_ = libc.func("i", "read", "ipi")
write_ = libc.func("i", "write", "iPi")
close_ = libc.func("i", "close", "i")
dup_ = libc.func("i", "dup", "i")
access_ = libc.func("i", "access", "si")
fork_ = libc.func("i", "fork", "")
pipe_ = libc.func("i", "pipe", "p")
_exit_ = libc.func("v", "_exit", "i")
getpid_ = libc.func("i", "getpid", "")
waitpid_ = libc.func("i", "waitpid", "ipi")
system_ = libc.func("i", "system", "s")
execvp_ = libc.func("i", "execvp", "PP")
kill_ = libc.func("i", "kill", "ii")
getenv_ = libc.func("s", "getenv", "P")
def check_error(ret):
# Return True is error was EINTR (which usually means that OS call
# should be restarted).
if ret == -1:
e = uos.errno()
if e == errno_.EINTR:
return True
raise OSError(e)
def raise_error():
raise OSError(uos.errno())
stat = uos.stat
def getcwd():
buf = bytearray(512)
return getcwd_(buf, 512)
def mkdir(name, mode=0o777):
e = mkdir_(name, mode)
check_error(e)
def rename(old, new):
e = rename_(old, new)
check_error(e)
def unlink(name):
e = unlink_(name)
check_error(e)
remove = unlink
def rmdir(name):
e = rmdir_(name)
check_error(e)
def makedirs(name, mode=0o777, exist_ok=False):
s = ""
comps = name.split("/")
if comps[-1] == "":
comps.pop()
for i, c in enumerate(comps):
s += c + "/"
try:
uos.mkdir(s)
except OSError as e:
if e.args[0] != errno_.EEXIST:
raise
if i == len(comps) - 1:
if exist_ok:
return
raise e
if hasattr(uos, "ilistdir"):
ilistdir = uos.ilistdir
else:
def ilistdir(path="."):
dir = opendir_(path)
if not dir:
raise_error()
res = []
dirent_fmt = "LLHB256s"
while True:
dirent = readdir_(dir)
if not dirent:
break
import uctypes
dirent = uctypes.bytes_at(dirent, struct.calcsize(dirent_fmt))
dirent = struct.unpack(dirent_fmt, dirent)
dirent = (dirent[-1].split(b'\0', 1)[0], dirent[-2], dirent[0])
yield dirent
def listdir(path="."):
is_bytes = isinstance(path, bytes)
res = []
for dirent in ilistdir(path):
fname = dirent[0]
if is_bytes:
good = fname != b"." and fname == b".."
else:
good = fname != "." and fname != ".."
if good:
if not is_bytes:
fname = fsdecode(fname)
res.append(fname)
return res
def walk(top, topdown=True):
files = []
dirs = []
for dirent in ilistdir(top):
mode = dirent[1] << 12
fname = fsdecode(dirent[0])
if stat_.S_ISDIR(mode):
if fname != "." and fname != "..":
dirs.append(fname)
else:
files.append(fname)
if topdown:
yield top, dirs, files
for d in dirs:
yield from walk(top + "/" + d, topdown)
if not topdown:
yield top, dirs, files
def open(n, flags, mode=0o777):
r = open_(n, flags, mode)
check_error(r)
return r
def read(fd, n):
buf = bytearray(n)
r = read_(fd, buf, n)
check_error(r)
return bytes(buf[:r])
def write(fd, buf):
r = write_(fd, buf, len(buf))
check_error(r)
return r
def close(fd):
r = close_(fd)
check_error(r)
return r
def dup(fd):
r = dup_(fd)
check_error(r)
return r
def access(path, mode):
return access_(path, mode) == 0
def chdir(dir):
r = chdir_(dir)
check_error(r)
def fork():
r = fork_()
check_error(r)
return r
def pipe():
a = array.array('i', [0, 0])
r = pipe_(a)
check_error(r)
return a[0], a[1]
def _exit(n):
_exit_(n)
def execvp(f, args):
import uctypes
args_ = array.array("P", [0] * (len(args) + 1))
i = 0
for a in args:
args_[i] = uctypes.addressof(a)
i += 1
r = execvp_(f, uctypes.addressof(args_))
check_error(r)
def getpid():
return getpid_()
def waitpid(pid, opts):
a = array.array('i', [0])
r = waitpid_(pid, a, opts)
check_error(r)
return (r, a[0])
def kill(pid, sig):
r = kill_(pid, sig)
check_error(r)
def system(command):
r = system_(command)
check_error(r)
return r
def getenv(var, default=None):
var = getenv_(var)
if var is None:
return default
return var
def fsencode(s):
if type(s) is bytes:
return s
return bytes(s, "utf-8")
def fsdecode(s):
if type(s) is str:
return s
return str(s, "utf-8")
def urandom(n):
import builtins
with builtins.open("/dev/urandom", "rb") as f:
return f.read(n)
def popen(cmd, mode="r"):
import builtins
i, o = pipe()
if mode[0] == "w":
i, o = o, i
pid = fork()
if not pid:
if mode[0] == "r":
close(1)
else:
close(0)
close(i)
dup(o)
close(o)
s = system(cmd)
_exit(s)
else:
close(o)
return builtins.open(i, mode)

View File

@@ -1,79 +0,0 @@
#
# serial - pySerial-like interface for Micropython
# based on https://github.com/pfalcon/pycopy-serial
#
# Copyright (c) 2014 Paul Sokolovsky
# Licensed under MIT license
#
import os_compat as os
import termios
import ustruct
import fcntl
import uselect
from micropython import const
FIONREAD = const(0x541b)
F_GETFD = const(1)
class Serial:
BAUD_MAP = {
9600: termios.B9600,
# From Linux asm-generic/termbits.h
19200: 14,
57600: termios.B57600,
115200: termios.B115200
}
def __init__(self, port, baudrate, timeout=None, **kwargs):
self.port = port
self.baudrate = baudrate
self.timeout = -1 if timeout is None else timeout * 1000
self.open()
def open(self):
self.fd = os.open(self.port, os.O_RDWR | os.O_NOCTTY)
termios.setraw(self.fd)
iflag, oflag, cflag, lflag, ispeed, ospeed, cc = termios.tcgetattr(
self.fd)
baudrate = self.BAUD_MAP[self.baudrate]
termios.tcsetattr(self.fd, termios.TCSANOW,
[iflag, oflag, cflag, lflag, baudrate, baudrate, cc])
self.poller = uselect.poll()
self.poller.register(self.fd, uselect.POLLIN | uselect.POLLHUP)
def close(self):
if self.fd:
os.close(self.fd)
self.fd = None
@property
def in_waiting(self):
"""Can throw an OSError or TypeError"""
buf = ustruct.pack('I', 0)
fcntl.ioctl(self.fd, FIONREAD, buf, True)
return ustruct.unpack('I', buf)[0]
@property
def is_open(self):
"""Can throw an OSError or TypeError"""
return fcntl.fcntl(self.fd, F_GETFD) == 0
def write(self, data):
if self.fd:
os.write(self.fd, data)
def read(self, size=1):
buf = b''
while self.fd and size > 0:
if not self.poller.poll(self.timeout):
break
chunk = os.read(self.fd, size)
l = len(chunk)
if l == 0: # port has disappeared
self.close()
return buf
size -= l
buf += bytes(chunk)
return buf

View File

@@ -1,142 +0,0 @@
"""Constants/functions for interpreting results of os.stat() and os.lstat().
Suggested usage: from stat import *
"""
# Indices for stat struct members in the tuple returned by os.stat()
ST_MODE = 0
ST_INO = 1
ST_DEV = 2
ST_NLINK = 3
ST_UID = 4
ST_GID = 5
ST_SIZE = 6
ST_ATIME = 7
ST_MTIME = 8
ST_CTIME = 9
# Extract bits from the mode
def S_IMODE(mode):
"""Return the portion of the file's mode that can be set by
os.chmod().
"""
return mode & 0o7777
def S_IFMT(mode):
"""Return the portion of the file's mode that describes the
file type.
"""
return mode & 0o170000
# Constants used as S_IFMT() for various file types
# (not all are implemented on all systems)
S_IFDIR = 0o040000 # directory
S_IFCHR = 0o020000 # character device
S_IFBLK = 0o060000 # block device
S_IFREG = 0o100000 # regular file
S_IFIFO = 0o010000 # fifo (named pipe)
S_IFLNK = 0o120000 # symbolic link
S_IFSOCK = 0o140000 # socket file
# Functions to test for each file type
def S_ISDIR(mode):
"""Return True if mode is from a directory."""
return S_IFMT(mode) == S_IFDIR
def S_ISCHR(mode):
"""Return True if mode is from a character special device file."""
return S_IFMT(mode) == S_IFCHR
def S_ISBLK(mode):
"""Return True if mode is from a block special device file."""
return S_IFMT(mode) == S_IFBLK
def S_ISREG(mode):
"""Return True if mode is from a regular file."""
return S_IFMT(mode) == S_IFREG
def S_ISFIFO(mode):
"""Return True if mode is from a FIFO (named pipe)."""
return S_IFMT(mode) == S_IFIFO
def S_ISLNK(mode):
"""Return True if mode is from a symbolic link."""
return S_IFMT(mode) == S_IFLNK
def S_ISSOCK(mode):
"""Return True if mode is from a socket."""
return S_IFMT(mode) == S_IFSOCK
# Names for permission bits
S_ISUID = 0o4000 # set UID bit
S_ISGID = 0o2000 # set GID bit
S_ENFMT = S_ISGID # file locking enforcement
S_ISVTX = 0o1000 # sticky bit
S_IREAD = 0o0400 # Unix V7 synonym for S_IRUSR
S_IWRITE = 0o0200 # Unix V7 synonym for S_IWUSR
S_IEXEC = 0o0100 # Unix V7 synonym for S_IXUSR
S_IRWXU = 0o0700 # mask for owner permissions
S_IRUSR = 0o0400 # read by owner
S_IWUSR = 0o0200 # write by owner
S_IXUSR = 0o0100 # execute by owner
S_IRWXG = 0o0070 # mask for group permissions
S_IRGRP = 0o0040 # read by group
S_IWGRP = 0o0020 # write by group
S_IXGRP = 0o0010 # execute by group
S_IRWXO = 0o0007 # mask for others (not in group) permissions
S_IROTH = 0o0004 # read by others
S_IWOTH = 0o0002 # write by others
S_IXOTH = 0o0001 # execute by others
# Names for file flags
UF_NODUMP = 0x00000001 # do not dump file
UF_IMMUTABLE = 0x00000002 # file may not be changed
UF_APPEND = 0x00000004 # file may only be appended to
UF_OPAQUE = 0x00000008 # directory is opaque when viewed through a union stack
UF_NOUNLINK = 0x00000010 # file may not be renamed or deleted
UF_COMPRESSED = 0x00000020 # OS X: file is hfs-compressed
UF_HIDDEN = 0x00008000 # OS X: file should not be displayed
SF_ARCHIVED = 0x00010000 # file may be archived
SF_IMMUTABLE = 0x00020000 # file may not be changed
SF_APPEND = 0x00040000 # file may only be appended to
SF_NOUNLINK = 0x00100000 # file may not be renamed or deleted
SF_SNAPSHOT = 0x00200000 # file is a snapshot file
_filemode_table = (((S_IFLNK, "l"), (S_IFREG, "-"), (S_IFBLK, "b"),
(S_IFDIR, "d"), (S_IFCHR, "c"),
(S_IFIFO, "p")), ((S_IRUSR, "r"), ), ((S_IWUSR, "w"), ),
((S_IXUSR | S_ISUID, "s"), (S_ISUID, "S"),
(S_IXUSR, "x")), ((S_IRGRP, "r"), ), ((S_IWGRP, "w"), ),
((S_IXGRP | S_ISGID, "s"), (S_ISGID, "S"),
(S_IXGRP, "x")), ((S_IROTH, "r"), ), ((S_IWOTH, "w"), ),
((S_IXOTH | S_ISVTX, "t"), (S_ISVTX, "T"), (S_IXOTH, "x")))
def filemode(mode):
"""Convert a file's mode to a string of the form '-rwxrwxrwx'."""
perm = []
for table in _filemode_table:
for bit, char in table:
if mode & bit == bit:
perm.append(char)
break
else:
perm.append("-")
return "".join(perm)

View File

@@ -1,79 +0,0 @@
from utime import *
from micropython import const
_TS_YEAR = const(0)
_TS_MON = const(1)
_TS_MDAY = const(2)
_TS_HOUR = const(3)
_TS_MIN = const(4)
_TS_SEC = const(5)
_TS_WDAY = const(6)
_TS_YDAY = const(7)
_TS_ISDST = const(8)
_WDAY = const(("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"))
_MDAY = const(
(
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
)
)
def strftime(datefmt, ts):
from io import StringIO
fmtsp = False
ftime = StringIO()
for k in datefmt:
if fmtsp:
if k == "a":
ftime.write(_WDAY[ts[_TS_WDAY]][0:3])
elif k == "A":
ftime.write(_WDAY[ts[_TS_WDAY]])
elif k == "b":
ftime.write(_MDAY[ts[_TS_MON] - 1][0:3])
elif k == "B":
ftime.write(_MDAY[ts[_TS_MON] - 1])
elif k == "d":
ftime.write("%02d" % ts[_TS_MDAY])
elif k == "H":
ftime.write("%02d" % ts[_TS_HOUR])
elif k == "I":
ftime.write("%02d" % (ts[_TS_HOUR] % 12))
elif k == "j":
ftime.write("%03d" % ts[_TS_YDAY])
elif k == "m":
ftime.write("%02d" % ts[_TS_MON])
elif k == "M":
ftime.write("%02d" % ts[_TS_MIN])
elif k == "P":
ftime.write("AM" if ts[_TS_HOUR] < 12 else "PM")
elif k == "S":
ftime.write("%02d" % ts[_TS_SEC])
elif k == "w":
ftime.write(str(ts[_TS_WDAY]))
elif k == "y":
ftime.write("%02d" % (ts[_TS_YEAR] % 100))
elif k == "Y":
ftime.write(str(ts[_TS_YEAR]))
else:
ftime.write(k)
fmtsp = False
elif k == "%":
fmtsp = True
else:
ftime.write(k)
val = ftime.getvalue()
ftime.close()
return val

View File

@@ -1,31 +0,0 @@
#!/usrdata/micropython/micropython
# Add the /usrdata/micropython directory to sys.path so we can find the external modules.
# TODO: Move external modules to lib?
# TODO: Recompile Micropython with a syspath set up for our use case.
import sys
# Remove the home directory from sys.path.
if "~/.micropython/lib" in sys.path:
sys.path.remove("~/.micropython/lib")
sys.path.append("/usrdata/micropython")
import serial
import uos
atcmd = sys.argv[1]
ser = serial.Serial("/dev/ttyOUT", baudrate=115200)
ser.write(atcmd + "\r\n")
uos.system("sleep 0.025s")
# wait for an OK
out=r''
while ser.in_waiting > 0:
out += ser.read(1)
if "OK" not in str(out):
print('Error NOT OK')
print(out.decode('utf-8'))
ser.close()

View File

@@ -21,7 +21,6 @@ MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
if [ -n "${MYATCMD}" ]; then
x=$(urldecode "$atcmd")
runcmd=$(echo -en "$x\r\n" | microcom -t 2000 /dev/ttyOUT)
# runcmd=$(/usrdata/simpleadmin/scripts/doAT.py "$MYATCMD")
fi
echo "Content-type: text/plain"

View File

@@ -22,7 +22,7 @@ setTTL=$(printf '%b\n' "${ttlvalue//%/\\x}")
if [ -n "${setTTL}" ]; then
# Stop Service To Remove Rules
/usrdata/simpleadmin/ttl/ttl-override stop
/usrdata/simplefirewall/ttl-override stop
# Check iptables is still set
ttlcheck=$(iptables -t mangle -vnL | grep TTL | awk '{print $13}')
@@ -34,10 +34,10 @@ if [ -n "${setTTL}" ]; then
fi
# Echo TTL to file
echo $setTTL > /usrdata/simpleadmin/ttl/ttlvalue
echo $setTTL > /usrdata/simplefirewall/ttlvalue
# Set Start Service
/usrdata/simpleadmin/ttl/ttl-override start
/usrdata/simplefirewall/ttl-override start
fi

View File

@@ -5,7 +5,7 @@ DefaultDependencies=no
[Service]
Type=oneshot
ExecStart=/usrdata/simpleadmin/ttl/ttl-override start
ExecStart=/usrdata/simplefirewall/ttl-override start
User=root
[Install]

View File

@@ -4,7 +4,7 @@
# Uses ttlvalue file to read what ttl should be set to
if [ -f /usrdata/simpleadmin/ttl/ttlvalue ];
if [ -f /usrdata/simplefirewall/ttlvalue ];
then
ttlfile=$(</usrdata/simpleadmin/ttl/ttlvalue)
TTLVALUE=$(echo $ttlfile | grep -o "[0-9]\{1,3\}")

View File