added advance settings functionality
This commit is contained in:
@@ -26,6 +26,8 @@
|
||||
<script src="/js/utils/restart-connection.js"></script>
|
||||
<script defer src="/js/auth/auth.js"></script>
|
||||
<script src="/js/advance/at-terminal.js"></script>
|
||||
<script src="/js/advance/ttl-control.js"></script>
|
||||
<script src="/js/advance/fetch-current.settings.js"></script>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
@@ -222,46 +224,72 @@
|
||||
<div class="card-content">
|
||||
<div class="fixed-grid has-1-cols">
|
||||
<div class="grid is-gap-5">
|
||||
<div class="cell">
|
||||
<div class="cell advanced-settings">
|
||||
<div class="fixed-grid has-2-cols has-1-cols-mobile">
|
||||
<div class="grid">
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">IP Passthrough Mode</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select>
|
||||
<option selected>
|
||||
Select IP Passthrough Mode
|
||||
</option>
|
||||
<option>Disable</option>
|
||||
<option>ETH Only</option>
|
||||
<option>USB Only</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-ethernet"></i>
|
||||
</span>
|
||||
</p>
|
||||
<p class="help">
|
||||
Selecting a mode will apply immediately.
|
||||
</p>
|
||||
<div class="cell is-col-span-2 is-col-span-1-mobile">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<div class="field">
|
||||
<label class="label">IP Passthrough Mode</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="ip-passthrough-mode">
|
||||
<option value="placeholder" selected>
|
||||
Select IP Passthrough Mode
|
||||
</option>
|
||||
<option value="Disabled">Disabled</option>
|
||||
<option value="ETH Only">ETH Only</option>
|
||||
<option value="USB Only">USB Only</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-ethernet"></i>
|
||||
</span>
|
||||
</p>
|
||||
<p class="help">
|
||||
This will reboot the device to apply changes.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column">
|
||||
<div class="field">
|
||||
<label class="label">Connected Devices MAC</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select id="connected-devices">
|
||||
<option selected>
|
||||
Select Device MAC
|
||||
</option>
|
||||
<!-- Populate the options here -->
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-laptop"></i>
|
||||
</span>
|
||||
</p>
|
||||
<p class="help">
|
||||
Selecting a device first before enabling.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="cell advanced-settings">
|
||||
<div class="field">
|
||||
<label class="label">USB Modem Protocol</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select>
|
||||
<select id="usb-modem-protocol">
|
||||
<option selected>
|
||||
Select USB Modem Protocol
|
||||
</option>
|
||||
<option>RMNET</option>
|
||||
<option>ECM (Recommended)</option>
|
||||
<option>MBIM</option>
|
||||
<option>RNDIS</option>
|
||||
<option value="RMNET">RMNET</option>
|
||||
<option value="ECM (Recommended)">ECM (Recommended)</option>
|
||||
<option value="MBIM">MBIM</option>
|
||||
<option value="RNDIS">RNDIS</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
@@ -269,22 +297,22 @@
|
||||
</span>
|
||||
</p>
|
||||
<p class="help">
|
||||
Selecting a mode will apply immediately.
|
||||
Selecting a mode will apply immediately. Requires reboot.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="cell advanced-settings">
|
||||
<div class="field">
|
||||
<label class="label">Onboard DNS Proxy Mode</label>
|
||||
<p class="control has-icons-left">
|
||||
<span class="select">
|
||||
<select>
|
||||
<select id="dns-proxy-mode">
|
||||
<option selected>
|
||||
Select Onboard DNS Proxy
|
||||
</option>
|
||||
<option>Enable</option>
|
||||
<option>Disable</option>
|
||||
<option value="Enabled">Enabled</option>
|
||||
<option value="Disabled">Disabled</option>
|
||||
</select>
|
||||
</span>
|
||||
<span class="icon is-small is-left">
|
||||
@@ -300,7 +328,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<!-- <div class="cell">
|
||||
<div class="fixed-grid has-2-cols">
|
||||
<div class="grid is-gap-3">
|
||||
<div class="cell">
|
||||
@@ -356,19 +384,81 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="cell">
|
||||
<div class="fixed-grid has-2-cols">
|
||||
<div class="grid is-gap-3">
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">TTL State</label>
|
||||
<div class="control has-icons-right">
|
||||
<input
|
||||
id="ttl-state"
|
||||
class="input is-warning has-text-weight-bold"
|
||||
placeholder="Disabled"
|
||||
disabled
|
||||
/>
|
||||
<span class="icon is-small is-right">
|
||||
<i
|
||||
class="fas fa-exclamation-triangle has-text-warning"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="field">
|
||||
<label class="label">Current TTL Value</label>
|
||||
<div class="control has-icons-right">
|
||||
<input
|
||||
id="ttl-current-value"
|
||||
class="input is-warning has-text-weight-bold has-text-white"
|
||||
placeholder="0"
|
||||
disabled
|
||||
/>
|
||||
<span class="icon is-small is-right">
|
||||
<i
|
||||
class="fas fa-exclamation-triangle has-text-warning"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell is-col-span-2">
|
||||
<div class="field">
|
||||
<label class="label">TTL Value to Set</label>
|
||||
<div class="control has-icons-left">
|
||||
<input
|
||||
id="ttl-set-value"
|
||||
class="input"
|
||||
type="number"
|
||||
placeholder="Custom TTL Value"
|
||||
/>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-wifi"></i>
|
||||
</span>
|
||||
</div>
|
||||
<p class="help is-success has-text-weight-semibold">
|
||||
Set the TTL Value to 0 to disable.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a
|
||||
href="#"
|
||||
id="ttl-submit"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Save
|
||||
Apply TTL Settings
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
class="card-footer-item has-text-link has-text-weight-semibold has-text-white"
|
||||
>
|
||||
Reset
|
||||
@@ -418,7 +508,7 @@
|
||||
<div class="modal-card">
|
||||
<section class="modal-card-body rounded-edge">
|
||||
<p class="subtitle" id="modal-message">
|
||||
Do you want to reboot the device?
|
||||
Do not do any action while the modem is rebooting.
|
||||
</p>
|
||||
<div id="loading-content" style="display: none">
|
||||
<div class="custom-loader"></div>
|
||||
|
||||
66
www/cgi-bin/advanced_settings.sh
Normal file
66
www/cgi-bin/advanced_settings.sh
Normal file
@@ -0,0 +1,66 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set content-type for JSON response
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Define the lock file
|
||||
LOCK_FILE="/tmp/home_data.lock"
|
||||
|
||||
# Acquire the lock (wait if needed)
|
||||
exec 200>$LOCK_FILE
|
||||
flock -x 200
|
||||
|
||||
# Temporary files for input/output and AT port
|
||||
INPUT_FILE="/tmp/input_$$.txt"
|
||||
OUTPUT_FILE="/tmp/output_$$.txt"
|
||||
AT_PORT="/dev/smd11"
|
||||
|
||||
# Debug file path
|
||||
DEBUG_FILE="/tmp/debug-json-result.txt"
|
||||
|
||||
# Function to escape JSON strings (handling quotes and newlines)
|
||||
escape_json() {
|
||||
# Escape newlines and double quotes
|
||||
echo "$1" | sed ':a;N;$!ba;s/\n/\\n/g; s/"/\\"/g'
|
||||
}
|
||||
|
||||
# Initialize JSON response array
|
||||
JSON_RESPONSE="["
|
||||
|
||||
# List of AT commands to run, one by one
|
||||
for COMMAND in 'AT+QMAP="MPDN_RULE"' 'AT+QMAP="DHCPV4DNS"' 'AT+QCFG="usbnet"'; do
|
||||
# Write the command to the input file
|
||||
echo "$COMMAND" > "$INPUT_FILE"
|
||||
|
||||
# Run the command using atinout
|
||||
atinout "$INPUT_FILE" "$AT_PORT" "$OUTPUT_FILE"
|
||||
|
||||
# Read the output from the output file
|
||||
OUTPUT=$(cat "$OUTPUT_FILE")
|
||||
|
||||
# Escape special characters for JSON (escape only output)
|
||||
ESCAPED_OUTPUT=$(escape_json "$OUTPUT")
|
||||
|
||||
# Append the response as an object to the JSON response array
|
||||
JSON_RESPONSE="${JSON_RESPONSE}{\"response\":\"$ESCAPED_OUTPUT\"},"
|
||||
done
|
||||
|
||||
# Remove the trailing comma and close the JSON array
|
||||
if [ "${JSON_RESPONSE: -1}" = "," ]; then
|
||||
JSON_RESPONSE="${JSON_RESPONSE%,}]"
|
||||
else
|
||||
JSON_RESPONSE="${JSON_RESPONSE}]"
|
||||
fi
|
||||
|
||||
# Write the JSON response to the debug file for troubleshooting
|
||||
echo "$JSON_RESPONSE" > "$DEBUG_FILE"
|
||||
|
||||
# Return the output as a valid JSON response
|
||||
echo "$JSON_RESPONSE"
|
||||
|
||||
# Clean up temporary files
|
||||
rm "$INPUT_FILE" "$OUTPUT_FILE"
|
||||
|
||||
# Release the lock
|
||||
flock -u 200
|
||||
49
www/cgi-bin/fetch_macs.sh
Normal file
49
www/cgi-bin/fetch_macs.sh
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/bin/sh
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# Create a temporary file to store the processed data
|
||||
temp_file=$(mktemp)
|
||||
|
||||
# Process ARP entries and store in temporary file
|
||||
arp -a | while IFS= read -r line; do
|
||||
if [ -n "$line" ]; then
|
||||
# Extract hostname (or IP if hostname is "?"), IP, and MAC
|
||||
hostname=$(echo "$line" | awk '{print $1}')
|
||||
ip=$(echo "$line" | awk -F '[()]' '{print $2}')
|
||||
mac=$(echo "$line" | awk '{print $4}')
|
||||
|
||||
# Skip entries without valid MAC addresses
|
||||
if [ "$mac" = "<incomplete>" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# If hostname is "?", use the IP address instead
|
||||
if [ "$hostname" = "?" ]; then
|
||||
hostname="$ip"
|
||||
fi
|
||||
|
||||
# Store each entry in the temp file
|
||||
echo "$hostname:$ip:$mac" >> "$temp_file"
|
||||
fi
|
||||
done
|
||||
|
||||
# Initialize JSON array
|
||||
echo -n "["
|
||||
|
||||
# Process the temporary file to create JSON
|
||||
first=true
|
||||
while IFS=: read -r hostname ip mac; do
|
||||
if [ "$first" = true ]; then
|
||||
first=false
|
||||
else
|
||||
echo -n ","
|
||||
fi
|
||||
echo -n "{\"hostname\":\"$hostname\",\"ip\":\"$ip\",\"mac\":\"$mac\"}"
|
||||
done < "$temp_file"
|
||||
|
||||
# Close the JSON array
|
||||
echo "]"
|
||||
|
||||
# Clean up
|
||||
rm -f "$temp_file"
|
||||
94
www/cgi-bin/ttl.sh
Normal file
94
www/cgi-bin/ttl.sh
Normal file
@@ -0,0 +1,94 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
ttl_file="/etc/firewall.user.ttl"
|
||||
lan_utils_script="/etc/data/lanUtils.sh"
|
||||
|
||||
setup_persistent_config() {
|
||||
if [ ! -f "$lan_utils_script" ]; then
|
||||
echo "{\"success\": false, \"error\": \"lanUtils.sh not found\"}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Backup the original script if not already done
|
||||
if [ ! -f "${lan_utils_script}.bak" ]; then
|
||||
cp "$lan_utils_script" "${lan_utils_script}.bak"
|
||||
fi
|
||||
|
||||
# Add the local ttl_firewall_file line if it's not already present
|
||||
if ! grep -q "local ttl_firewall_file" "$lan_utils_script"; then
|
||||
sed -i '/local tcpmss_firewall_filev6/a \ local ttl_firewall_file=/etc/firewall.user.ttl' "$lan_utils_script"
|
||||
fi
|
||||
|
||||
# Add the condition to include the ttl_firewall_file if it's not already present
|
||||
if ! grep -q "if \[ -f \"\$ttl_firewall_file\" \]; then" "$lan_utils_script"; then
|
||||
sed -i '/if \[ -f "\$tcpmss_firewall_filev6" \]; then/i \ if [ -f "\$ttl_firewall_file" ]; then\n cat \$ttl_firewall_file >> \$firewall_file\n fi' "$lan_utils_script"
|
||||
fi
|
||||
}
|
||||
|
||||
clear_existing_rules() {
|
||||
local current_ttl=$1
|
||||
if [ -n "$current_ttl" ]; then
|
||||
iptables -t mangle -D POSTROUTING -o rmnet+ -j TTL --ttl-set "$current_ttl" 2>/dev/null
|
||||
ip6tables -t mangle -D POSTROUTING -o rmnet+ -j HL --hl-set "$current_ttl" 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
case "$REQUEST_METHOD" in
|
||||
GET)
|
||||
# Ensure consistent JSON format for GET requests
|
||||
if [ -s "$ttl_file" ]; then
|
||||
ttl_value=$(grep 'iptables -t mangle -A POSTROUTING' "$ttl_file" | awk '{for(i=1;i<=NF;i++){if($i=="--ttl-set"){print $(i+1)}}}')
|
||||
# Ensure ttl_value is a number, default to 0 if not
|
||||
if ! [[ "$ttl_value" =~ ^[0-9]+$ ]]; then
|
||||
ttl_value=0
|
||||
fi
|
||||
echo "{\"isEnabled\": true, \"currentValue\": $ttl_value}"
|
||||
else
|
||||
echo "{\"isEnabled\": false, \"currentValue\": 0}"
|
||||
fi
|
||||
;;
|
||||
POST)
|
||||
read -r post_data
|
||||
ttl_value=$(echo "$post_data" | sed 's/ttl=//')
|
||||
|
||||
# Ensure ttl_file exists
|
||||
touch "$ttl_file" 2>/dev/null
|
||||
if [ ! -f "$ttl_file" ]; then
|
||||
echo "{\"success\": false, \"error\": \"Cannot create TTL file\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Setup persistent configuration
|
||||
setup_persistent_config
|
||||
|
||||
# Get current TTL value for cleanup
|
||||
current_ttl=$(grep 'iptables -t mangle -A POSTROUTING' "$ttl_file" | awk '{for(i=1;i<=NF;i++){if($i=="--ttl-set"){print $(i+1)}}}')
|
||||
|
||||
if ! [[ "$ttl_value" =~ ^[0-9]+$ ]]; then
|
||||
echo "{\"success\": false, \"error\": \"Invalid TTL value\"}"
|
||||
elif [ "$ttl_value" = "0" ]; then
|
||||
clear_existing_rules "$current_ttl"
|
||||
> "$ttl_file"
|
||||
echo "{\"success\": true}"
|
||||
else
|
||||
# Clear existing rules
|
||||
clear_existing_rules "$current_ttl"
|
||||
|
||||
# Set new rules
|
||||
echo "iptables -t mangle -A POSTROUTING -o rmnet+ -j TTL --ttl-set $ttl_value" > "$ttl_file"
|
||||
echo "ip6tables -t mangle -A POSTROUTING -o rmnet+ -j HL --hl-set $ttl_value" >> "$ttl_file"
|
||||
|
||||
# Apply the rules
|
||||
iptables -t mangle -A POSTROUTING -o rmnet+ -j TTL --ttl-set "$ttl_value"
|
||||
ip6tables -t mangle -A POSTROUTING -o rmnet+ -j HL --hl-set "$ttl_value"
|
||||
|
||||
echo "{\"success\": true}"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "{\"success\": false, \"error\": \"Invalid request method\"}"
|
||||
;;
|
||||
esac
|
||||
461
www/js/advance/fetch-current.settings.js
Normal file
461
www/js/advance/fetch-current.settings.js
Normal file
@@ -0,0 +1,461 @@
|
||||
async function fetchCurrentSettings() {
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/advanced_settings.sh");
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log("Current settings:", data);
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Error fetching current settings:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchConnectedDevices() {
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/fetch_macs.sh");
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log("Connected devices:", data);
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Error fetching connected devices:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function populateConnectedDevices(devices) {
|
||||
const selectElement = document.getElementById("connected-devices");
|
||||
if (!selectElement) {
|
||||
console.error("Connected devices select element not found");
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear existing options except the first one
|
||||
while (selectElement.options.length > 1) {
|
||||
selectElement.remove(1);
|
||||
}
|
||||
|
||||
// Add new options
|
||||
devices.forEach((device) => {
|
||||
const option = document.createElement("option");
|
||||
option.value = device.mac;
|
||||
option.textContent = `${device.hostname} - ${device.mac}`;
|
||||
selectElement.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
function updatePassthroughModeState(isEnabled) {
|
||||
const ipPassthroughSelect = document.getElementById("ip-passthrough-mode");
|
||||
if (!ipPassthroughSelect) return;
|
||||
|
||||
if (isEnabled) {
|
||||
ipPassthroughSelect.removeAttribute("disabled");
|
||||
ipPassthroughSelect.classList.remove("is-warning");
|
||||
const helpText = ipPassthroughSelect.parentElement.querySelector(".help");
|
||||
if (helpText) {
|
||||
helpText.textContent = "Select a passthrough mode to apply.";
|
||||
helpText.classList.remove("is-warning");
|
||||
helpText.classList.add("is-info");
|
||||
}
|
||||
} else {
|
||||
ipPassthroughSelect.setAttribute("disabled", "disabled");
|
||||
ipPassthroughSelect.classList.add("is-warning");
|
||||
ipPassthroughSelect.value = "Select IP Passthrough Mode";
|
||||
const helpText = ipPassthroughSelect.parentElement.querySelector(".help");
|
||||
if (helpText) {
|
||||
helpText.textContent = "Please select a device first.";
|
||||
helpText.classList.remove("is-info");
|
||||
helpText.classList.add("is-warning");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateUIElements(data) {
|
||||
// Get all required DOM elements
|
||||
const elements = {
|
||||
ipPassthrough: document.getElementById("ip-passthrough-mode"),
|
||||
dnsProxy: document.getElementById("dns-proxy-mode"),
|
||||
usbModem: document.getElementById("usb-modem-protocol"),
|
||||
};
|
||||
|
||||
// Check if all elements exist
|
||||
const missingElements = Object.entries(elements)
|
||||
.filter(([key, element]) => !element)
|
||||
.map(([key]) => key);
|
||||
|
||||
if (missingElements.length > 0) {
|
||||
console.error("Missing DOM elements:", missingElements);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// Initially disable IP Passthrough mode
|
||||
updatePassthroughModeState(false);
|
||||
|
||||
// Passthrough Mode (will be disabled until device is selected)
|
||||
const mpdnRuleLine = data[0].response.split("\n")[1];
|
||||
if (mpdnRuleLine) {
|
||||
const mpdnRule = mpdnRuleLine.split(":")[1].trim();
|
||||
switch (mpdnRule) {
|
||||
case '"MPDN_rule",0,0,0,0,0':
|
||||
elements.ipPassthrough.value = "Disabled";
|
||||
break;
|
||||
case '"MPDN_rule",0,1,0,1,1':
|
||||
elements.ipPassthrough.value = "ETH Only";
|
||||
break;
|
||||
case '"MPDN_rule",0,1,0,3,1':
|
||||
elements.ipPassthrough.value = "USB Only";
|
||||
break;
|
||||
default:
|
||||
elements.ipPassthrough.value = "Select IP Passthrough Mode";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// DNS Proxy
|
||||
const dnsProxyLine = data[1].response
|
||||
.split("\n")[1]
|
||||
.split(":")[1]
|
||||
.split(",")[1]
|
||||
.trim();
|
||||
if (dnsProxyLine) {
|
||||
elements.dnsProxy.value =
|
||||
dnsProxyLine === '"disable"' ? "Disabled" : "Enabled";
|
||||
} else {
|
||||
elements.dnsProxy.value = "Select Onboard DNS Proxy";
|
||||
}
|
||||
|
||||
// USB Modem Protocol
|
||||
const usbModemProtocolLine = data[2].response
|
||||
.split("\n")[1]
|
||||
.split(":")[1]
|
||||
.split(",")[1]
|
||||
.trim();
|
||||
switch (usbModemProtocolLine) {
|
||||
case "0":
|
||||
elements.usbModem.value = "RMNET";
|
||||
break;
|
||||
case "1":
|
||||
elements.usbModem.value = "ECM (Recommended)";
|
||||
break;
|
||||
case "2":
|
||||
elements.usbModem.value = "MBIM";
|
||||
break;
|
||||
case "3":
|
||||
elements.usbModem.value = "RNDIS";
|
||||
break;
|
||||
default:
|
||||
elements.usbModem.value = "Select USB Modem Protocol";
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Error updating UI elements:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to send an AT command based on the DNS proxy mode
|
||||
async function sendDnsProxyCommand(command) {
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
body: "command=" + encodeURIComponent(command),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
console.log("DNS Proxy AT command executed:", data.output);
|
||||
} catch (error) {
|
||||
console.error("Error sending DNS Proxy AT command:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle DNS Proxy changes
|
||||
function handleDnsProxyChange() {
|
||||
const dnsProxySelect = document.getElementById("dns-proxy-mode");
|
||||
const currentDnsProxyMode = dnsProxySelect.getAttribute("data-current-mode"); // Store current mode as a data attribute
|
||||
|
||||
dnsProxySelect.addEventListener("change", function (e) {
|
||||
const selectedMode = e.target.value;
|
||||
|
||||
// Send AT command only if the selected mode differs from the current one
|
||||
if (selectedMode !== currentDnsProxyMode) {
|
||||
if (selectedMode === "Enabled") {
|
||||
sendDnsProxyCommand('AT+QMAP="DHCPV4DNS","enable"');
|
||||
} else if (selectedMode === "Disabled") {
|
||||
sendDnsProxyCommand('AT+QMAP="DHCPV4DNS","disable"');
|
||||
}
|
||||
} else {
|
||||
console.log("No changes made to DNS Proxy mode");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Function to send an AT command based on the IP Passthrough mode
|
||||
async function sendIpPassthroughCommand(command) {
|
||||
if (command) {
|
||||
showLoadingContent(); // Show loading content and hide the buttons
|
||||
startCountdown(80); // Start the countdown for 5 seconds
|
||||
}
|
||||
try {
|
||||
const response = await fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
body: "command=" + encodeURIComponent(command),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
console.log("IP Passthrough AT command executed:", data.output);
|
||||
} catch (error) {
|
||||
console.error("Error sending IP Passthrough AT command:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle IP Passthrough mode changes
|
||||
function handleIpPassthroughChange() {
|
||||
// track if the device is selected by listening to the connected devices dropdown change event
|
||||
const connectedDevicesSelect = document.getElementById("connected-devices");
|
||||
if (connectedDevicesSelect) {
|
||||
connectedDevicesSelect.addEventListener("change", function (e) {
|
||||
const selectedMAC = e.target.value;
|
||||
const selectedHostname = e.target.options[e.target.selectedIndex].text;
|
||||
console.log("Selected device:", {
|
||||
mac: selectedMAC,
|
||||
hostname: selectedHostname,
|
||||
});
|
||||
|
||||
// Enable/disable IP Passthrough mode based on selection
|
||||
const isDeviceSelected = selectedMAC !== "Select Device MAC";
|
||||
if (isDeviceSelected) {
|
||||
updatePassthroughModeState(true);
|
||||
} else {
|
||||
updatePassthroughModeState(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const ipPassthroughSelect = document.getElementById("ip-passthrough-mode");
|
||||
const currentIpPassthroughMode =
|
||||
ipPassthroughSelect.getAttribute("data-current-mode"); // Store current mode as a data attribute
|
||||
|
||||
ipPassthroughSelect.addEventListener("change", function (e) {
|
||||
const selectedMode = e.target.value;
|
||||
const selectedDeviceMAC =
|
||||
document.getElementById("connected-devices").value;
|
||||
|
||||
// Send AT command only if the selected mode differs from the current one
|
||||
if (selectedMode !== currentIpPassthroughMode) {
|
||||
let command;
|
||||
switch (selectedMode) {
|
||||
case "Disabled":
|
||||
command = 'AT+QMPDN="MPDN_rule",0;+CFUN=1,1';
|
||||
break;
|
||||
case "ETH Only":
|
||||
command = `AT+QMPDN="MPDN_rule",0,1,0,1,1,"${selectedDeviceMAC}"`;
|
||||
break;
|
||||
case "USB Only":
|
||||
command = `AT+QMPDN="MPDN_rule",0,1,0,3,1,"${selectedDeviceMAC}"`;
|
||||
break;
|
||||
default:
|
||||
console.error("Invalid IP Passthrough mode:", selectedMode);
|
||||
return;
|
||||
}
|
||||
|
||||
sendIpPassthroughCommand(command);
|
||||
} else {
|
||||
console.log("No changes made to IP Passthrough mode");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Function to send an AT command based on the USB Modem Protocol
|
||||
async function sendUsbModemProtocolCommand(command) {
|
||||
try {
|
||||
if (command) {
|
||||
showLoadingContent(); // Show loading content and hide the buttons
|
||||
startCountdown(80); // Start the countdown for 5 seconds
|
||||
}
|
||||
const response = await fetch("/cgi-bin/atinout_handler.sh", {
|
||||
method: "POST",
|
||||
body: "command=" + encodeURIComponent(command),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
console.log("USB Modem Protocol AT command executed:", data.output);
|
||||
} catch (error) {
|
||||
console.error("Error sending USB Modem Protocol AT command:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle USB Modem Protocol changes
|
||||
function handleUsbModemProtocolChange() {
|
||||
const usbModemSelect = document.getElementById("usb-modem-protocol");
|
||||
const currentUsbModemProtocol = usbModemSelect.getAttribute(
|
||||
"data-current-protocol"
|
||||
); // Store current protocol as a data attribute
|
||||
|
||||
usbModemSelect.addEventListener("change", function (e) {
|
||||
const selectedProtocol = e.target.value;
|
||||
|
||||
// Send AT command only if the selected protocol differs from the current one
|
||||
if (selectedProtocol !== currentUsbModemProtocol) {
|
||||
let command;
|
||||
switch (selectedProtocol) {
|
||||
case "RMNET":
|
||||
command = 'AT+QCFG="usbnet",0;+CFUN=1,1';
|
||||
break;
|
||||
case "ECM (Recommended)":
|
||||
command = 'AT+QCFG="usbnet",1;+CFUN=1,1';
|
||||
break;
|
||||
case "MBIM":
|
||||
command = 'AT+QCFG="usbnet",2;+CFUN=1,1';
|
||||
break;
|
||||
case "RNDIS":
|
||||
command = 'AT+QCFG="usbnet",3;+CFUN=1,1';
|
||||
break;
|
||||
default:
|
||||
console.error("Invalid USB Modem Protocol:", selectedProtocol);
|
||||
return;
|
||||
}
|
||||
|
||||
sendUsbModemProtocolCommand(command);
|
||||
} else {
|
||||
console.log("No changes made to USB Modem Protocol");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Function to show the modal
|
||||
function showModal() {
|
||||
const modal = document.getElementById("reboot-modal");
|
||||
if (modal) {
|
||||
modal.classList.add("is-active"); // Bulma modals require "is-active" to be shown
|
||||
}
|
||||
}
|
||||
|
||||
// Function to show loading content and show the modal
|
||||
function showLoadingContent() {
|
||||
document.getElementById("loading-content").style.display = "flex"; // Show the loading section
|
||||
document.getElementById("modal-buttons").style.display = "none"; // Hide the buttons
|
||||
|
||||
// Activate the modal
|
||||
showModal();
|
||||
}
|
||||
|
||||
// Function to start the countdown
|
||||
function startCountdown(duration) {
|
||||
let countdownElement = document.getElementById("countdown");
|
||||
let countdown = duration;
|
||||
let interval = setInterval(function () {
|
||||
countdown--;
|
||||
countdownElement.textContent = countdown;
|
||||
|
||||
if (countdown <= 0) {
|
||||
clearInterval(interval);
|
||||
// Add any additional logic after countdown reaches 0 (like reloading or closing the modal)
|
||||
location.reload(); // Reload the page
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Function for initializing the page
|
||||
function init() {
|
||||
// Replace all i elements under the class advanced-settings with a spinner icon initially
|
||||
const advancedSettingsIcons = document.querySelectorAll(
|
||||
".advanced-settings i"
|
||||
);
|
||||
advancedSettingsIcons.forEach((icon) => {
|
||||
icon.classList.add("fa-spinner", "fa-spin");
|
||||
});
|
||||
|
||||
Promise.all([fetchCurrentSettings(), fetchConnectedDevices()])
|
||||
.then(([settings, devices]) => {
|
||||
if (settings) {
|
||||
const updateSuccess = updateUIElements(settings);
|
||||
if (!updateSuccess) {
|
||||
console.error("Failed to update UI elements");
|
||||
} else {
|
||||
// Revert the spinner icons back to their original state
|
||||
advancedSettingsIcons.forEach((icon) => {
|
||||
icon.classList.remove("fa-spinner", "fa-spin");
|
||||
});
|
||||
|
||||
handleDnsProxyChange(); // Add event listener for DNS Proxy changes
|
||||
handleUsbModemProtocolChange(); // Add event listener for USB Modem Protocol changes
|
||||
handleIpPassthroughChange(); // Add event listener for IP Passthrough changes
|
||||
}
|
||||
} else {
|
||||
console.error("Failed to fetch current settings");
|
||||
}
|
||||
|
||||
if (devices) {
|
||||
populateConnectedDevices(devices);
|
||||
} else {
|
||||
console.error("Failed to fetch connected devices");
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error during initialization:", error);
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize event listeners when DOM is ready
|
||||
// document.addEventListener("DOMContentLoaded", () => {
|
||||
// // Initialize the page
|
||||
// init();
|
||||
|
||||
// // Add event listener for usb modem protocol changes
|
||||
// handleUsbModemProtocolChange();
|
||||
|
||||
// // Add event listener for connected devices dropdown
|
||||
// const connectedDevicesSelect = document.getElementById("connected-devices");
|
||||
// if (connectedDevicesSelect) {
|
||||
// connectedDevicesSelect.addEventListener("change", function (e) {
|
||||
// const selectedMAC = e.target.value;
|
||||
// const selectedHostname = e.target.options[e.target.selectedIndex].text;
|
||||
// console.log("Selected device:", {
|
||||
// mac: selectedMAC,
|
||||
// hostname: selectedHostname,
|
||||
// });
|
||||
|
||||
// // Enable/disable IP Passthrough mode based on selection
|
||||
// const isDeviceSelected = selectedMAC !== "Select Device MAC";
|
||||
// updatePassthroughModeState(isDeviceSelected);
|
||||
// });
|
||||
// }
|
||||
|
||||
// // Add event listener for IP Passthrough mode changes
|
||||
// const ipPassthroughSelect = document.getElementById("ip-passthrough-mode");
|
||||
// if (ipPassthroughSelect) {
|
||||
// ipPassthroughSelect.addEventListener("change", function (e) {
|
||||
// const selectedMode = e.target.value;
|
||||
// const connectedDevicesSelect =
|
||||
// document.getElementById("connected-devices");
|
||||
// const selectedMAC = connectedDevicesSelect
|
||||
// ? connectedDevicesSelect.value
|
||||
// : null;
|
||||
|
||||
// if (selectedMAC && selectedMAC !== "Select Device MAC") {
|
||||
// console.log("Applying IP Passthrough mode:", {
|
||||
// mode: selectedMode,
|
||||
// deviceMAC: selectedMAC,
|
||||
// });
|
||||
// // Here you can add the API call to apply the passthrough mode
|
||||
// } else {
|
||||
// console.error("No device selected for IP Passthrough mode");
|
||||
// e.target.value = "Select IP Passthrough Mode";
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// Initialize event listeners when DOM is ready
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Initialize the page
|
||||
init();
|
||||
});
|
||||
94
www/js/advance/ttl-control.js
Normal file
94
www/js/advance/ttl-control.js
Normal file
@@ -0,0 +1,94 @@
|
||||
// TTL Control functionality
|
||||
const TTLControl = {
|
||||
async getCurrentState() {
|
||||
try {
|
||||
const response = await fetch('/cgi-bin/ttl.sh');
|
||||
const data = await response.json();
|
||||
return {
|
||||
isEnabled: data.isEnabled,
|
||||
currentValue: data.currentValue || 0
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error fetching TTL state:', error);
|
||||
return { isEnabled: false, currentValue: 0 };
|
||||
}
|
||||
},
|
||||
|
||||
async setTTLValue(value) {
|
||||
try {
|
||||
const response = await fetch('/cgi-bin/ttl.sh', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: `ttl=${value}`
|
||||
});
|
||||
const result = await response.json();
|
||||
return result.success;
|
||||
} catch (error) {
|
||||
console.error('Error setting TTL value:', error);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
updateUI(isEnabled, value) {
|
||||
const stateInput = document.getElementById('ttl-state');
|
||||
const valueInput = document.getElementById('ttl-current-value');
|
||||
const stateIcon = stateInput.nextElementSibling.querySelector('i');
|
||||
const valueIcon = valueInput.nextElementSibling.querySelector('i');
|
||||
|
||||
// Update State UI
|
||||
if (isEnabled) {
|
||||
// Enabled state
|
||||
stateInput.value = 'Enabled';
|
||||
stateInput.classList.remove('has-text-warning', 'is-danger');
|
||||
stateInput.classList.add('has-text-success', 'has-text-weight-bold');
|
||||
stateIcon.classList.remove('fa-exclamation-triangle', 'has-text-warning');
|
||||
stateIcon.classList.add('fa-check', 'has-text-success');
|
||||
} else {
|
||||
// Disabled state
|
||||
stateInput.value = 'Disabled';
|
||||
stateInput.classList.remove('has-text-success', 'is-danger');
|
||||
stateInput.classList.add('has-text-warning', 'has-text-weight-bold');
|
||||
stateIcon.classList.remove('fa-check', 'has-text-success');
|
||||
stateIcon.classList.add('fa-exclamation-triangle', 'has-text-warning');
|
||||
}
|
||||
|
||||
// Update Value UI
|
||||
valueInput.value = value.toString();
|
||||
valueInput.classList.add('has-text-weight-bold', 'has-text-white');
|
||||
if (isEnabled) {
|
||||
valueIcon.classList.remove('fa-exclamation-triangle', 'has-text-warning');
|
||||
valueIcon.classList.add('fa-check', 'has-text-success');
|
||||
} else {
|
||||
valueIcon.classList.remove('fa-check', 'has-text-success');
|
||||
valueIcon.classList.add('fa-exclamation-triangle', 'has-text-warning');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Event Listeners
|
||||
document.addEventListener('DOMContentLoaded', async function() {
|
||||
// Initial state fetch
|
||||
const { isEnabled, currentValue } = await TTLControl.getCurrentState();
|
||||
TTLControl.updateUI(isEnabled, currentValue);
|
||||
|
||||
// Submit button event listener
|
||||
document.getElementById('ttl-submit').addEventListener('click', async function() {
|
||||
const newValue = document.getElementById('ttl-set-value').value;
|
||||
const numValue = parseInt(newValue);
|
||||
|
||||
if (isNaN(numValue) || numValue < 0) {
|
||||
alert('Please enter a valid TTL value (0 or positive number)');
|
||||
return;
|
||||
}
|
||||
|
||||
const success = await TTLControl.setTTLValue(numValue);
|
||||
if (success) {
|
||||
TTLControl.updateUI(numValue !== 0, numValue);
|
||||
alert('TTL settings updated successfully');
|
||||
} else {
|
||||
alert('Failed to update TTL settings');
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user