mirror of
https://github.com/vdsm/virtual-dsm.git
synced 2026-08-29 20:26:57 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63e4529eff | ||
|
|
afd848cebb | ||
|
|
695b075130 | ||
|
|
7eff53e722 | ||
|
|
bcaf0e5980 | ||
|
|
faa820c2cc | ||
|
|
81e477fcc4 | ||
|
|
abd3a1c3df | ||
|
|
3b59bcd284 | ||
|
|
f1b56f394a | ||
|
|
1a983ebcd1 | ||
|
|
41c76198fa | ||
|
|
222b5649b0 | ||
|
|
e14fd4b711 |
+268
-1
@@ -1 +1,268 @@
|
|||||||
build.sh
|
##############################
|
||||||
|
# Operating System Files
|
||||||
|
##############################
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
Icon?
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
.Spotlight-V100/
|
||||||
|
.Trashes/
|
||||||
|
.fseventsd
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# IDEs
|
||||||
|
##############################
|
||||||
|
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# VS Code
|
||||||
|
##############################
|
||||||
|
|
||||||
|
.history/
|
||||||
|
*.code-workspace
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Vim
|
||||||
|
##############################
|
||||||
|
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
Session.vim
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Sublime
|
||||||
|
##############################
|
||||||
|
|
||||||
|
*.sublime-workspace
|
||||||
|
*.sublime-project
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Temporary Files
|
||||||
|
##############################
|
||||||
|
|
||||||
|
*.tmp
|
||||||
|
*.temp
|
||||||
|
*.bak
|
||||||
|
*.old
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
*.save
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Logs
|
||||||
|
##############################
|
||||||
|
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
log/
|
||||||
|
*.out
|
||||||
|
*.err
|
||||||
|
*.trace
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Runtime
|
||||||
|
##############################
|
||||||
|
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Secrets
|
||||||
|
##############################
|
||||||
|
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
*.pem
|
||||||
|
*.key
|
||||||
|
*.crt
|
||||||
|
*.cer
|
||||||
|
*.p12
|
||||||
|
*.pfx
|
||||||
|
*.kdbx
|
||||||
|
*.secret
|
||||||
|
*.token
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# SSH
|
||||||
|
##############################
|
||||||
|
|
||||||
|
.ssh/
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Docker
|
||||||
|
##############################
|
||||||
|
|
||||||
|
docker-compose.override.yml
|
||||||
|
docker-compose.local.yml
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# VM Storage
|
||||||
|
##############################
|
||||||
|
|
||||||
|
storage/
|
||||||
|
windows/
|
||||||
|
downloads/
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Disk Images
|
||||||
|
##############################
|
||||||
|
|
||||||
|
*.qcow2
|
||||||
|
*.qcow
|
||||||
|
*.vhd
|
||||||
|
*.vhdx
|
||||||
|
*.vdi
|
||||||
|
*.raw
|
||||||
|
*.img
|
||||||
|
*.iso
|
||||||
|
*.bin
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# QEMU
|
||||||
|
##############################
|
||||||
|
|
||||||
|
*.nvram
|
||||||
|
*.fd
|
||||||
|
*.efi
|
||||||
|
*.sock
|
||||||
|
*.monitor
|
||||||
|
*.serial
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Samba
|
||||||
|
##############################
|
||||||
|
|
||||||
|
shared/
|
||||||
|
share/
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Backups
|
||||||
|
##############################
|
||||||
|
|
||||||
|
backup/
|
||||||
|
backups/
|
||||||
|
*.backup
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Cache
|
||||||
|
##############################
|
||||||
|
|
||||||
|
.cache/
|
||||||
|
.cache-loader/
|
||||||
|
.tmp/
|
||||||
|
temp/
|
||||||
|
tmp/
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Python
|
||||||
|
##############################
|
||||||
|
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
.pytest_cache/
|
||||||
|
.mypy_cache/
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Node
|
||||||
|
##############################
|
||||||
|
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Build
|
||||||
|
##############################
|
||||||
|
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
out/
|
||||||
|
release/
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Coverage
|
||||||
|
##############################
|
||||||
|
|
||||||
|
coverage/
|
||||||
|
.coverage
|
||||||
|
coverage.xml
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Archives
|
||||||
|
##############################
|
||||||
|
|
||||||
|
*.zip
|
||||||
|
*.tar
|
||||||
|
*.tar.gz
|
||||||
|
*.tgz
|
||||||
|
*.7z
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Generated Config
|
||||||
|
##############################
|
||||||
|
|
||||||
|
config.local.*
|
||||||
|
settings.local.*
|
||||||
|
local.env
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Test Files
|
||||||
|
##############################
|
||||||
|
|
||||||
|
test-output/
|
||||||
|
playwright-report/
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# macOS
|
||||||
|
##############################
|
||||||
|
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Linux
|
||||||
|
##############################
|
||||||
|
|
||||||
|
*~
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Windows
|
||||||
|
##############################
|
||||||
|
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Misc
|
||||||
|
##############################
|
||||||
|
|
||||||
|
*.cache
|
||||||
|
*.lock
|
||||||
|
*.lock.json
|
||||||
|
*.bak.*
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# Keep Examples
|
||||||
|
##############################
|
||||||
|
|
||||||
|
!.gitkeep
|
||||||
|
!.env.example
|
||||||
|
|||||||
+5
-5
@@ -8,8 +8,8 @@ An empty default means the variable is unset and its value is determined automat
|
|||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `URL` | | URL or local path to the DSM `.pat` installation file. Downloads the default Virtual DSM image automatically when unset. |
|
| `URL` | | URL or local path to a custom `.pat` installation file. |
|
||||||
| `COUNTRY` | | Country code used to select the Synology download mirror. Detected automatically when unset. |
|
| `COUNTRY` | | Country code used to select the Synology download mirror. |
|
||||||
| `HOST_MAC` | | MAC address reported to DSM. |
|
| `HOST_MAC` | | MAC address reported to DSM. |
|
||||||
| `HOST_MODEL` | | Synology host model reported to DSM. |
|
| `HOST_MODEL` | | Synology host model reported to DSM. |
|
||||||
| `HOST_SERIAL` | | Synology host serial number reported to DSM. |
|
| `HOST_SERIAL` | | Synology host serial number reported to DSM. |
|
||||||
@@ -47,14 +47,14 @@ An empty default means the variable is unset and its value is determined automat
|
|||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `NETWORK` | | Network mode, such as `nat`, `user`, or `N` to disable networking. |
|
| `NETWORK` | | Network mode, such as `nat`, `user`, or `N` to disable networking. |
|
||||||
| `DHCP` | `N` | Enables macvtap networking so DSM receives an address from the external LAN through DHCP. |
|
| `DHCP` | `N` | Enables macvtap networking so DSM receives a DHCP address. |
|
||||||
| `HOST` | `VirtualDSM` | Hostname assigned to DSM. |
|
| `HOST` | | Hostname assigned to the machine on the network. |
|
||||||
| `IP` | | Overrides the automatically selected guest IPv4 address. |
|
| `IP` | | Overrides the automatically selected guest IPv4 address. |
|
||||||
| `MAC` | | Guest network adapter MAC address. |
|
| `MAC` | | Guest network adapter MAC address. |
|
||||||
| `ADAPTER` | `virtio-net-pci` | QEMU network adapter model. |
|
| `ADAPTER` | `virtio-net-pci` | QEMU network adapter model. |
|
||||||
| `DEV` | `eth0` | Container network interface used as the uplink. |
|
| `DEV` | `eth0` | Container network interface used as the uplink. |
|
||||||
| `MTU` | | MTU assigned to the guest network interface. |
|
| `MTU` | | MTU assigned to the guest network interface. |
|
||||||
| `MASK` | `255.255.255.0` | IPv4 netmask. |
|
| `MASK` | `255.255.255.0` | IPv4 netmask for guest network. |
|
||||||
| `TAP` | `dsm` | TAP or macvtap interface name. |
|
| `TAP` | `dsm` | TAP or macvtap interface name. |
|
||||||
| `BRIDGE` | `docker` | Bridge name used for NAT networking. |
|
| `BRIDGE` | `docker` | Bridge name used for NAT networking. |
|
||||||
| `HOST_PORTS` | | Ports excluded from guest forwarding. |
|
| `HOST_PORTS` | | Ports excluded from guest forwarding. |
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ file="/run/shm/dsm.url"
|
|||||||
address="/run/shm/qemu.ip"
|
address="/run/shm/qemu.ip"
|
||||||
gateway="/run/shm/qemu.gw"
|
gateway="/run/shm/qemu.gw"
|
||||||
|
|
||||||
[ ! -s "$file" ] && echo "DSM has not enabled networking yet..." && exit 1
|
[ ! -s "$file" ] && echo "DSM has not enabled networking yet..." && exit 0
|
||||||
|
|
||||||
location=$(<"$file")
|
location=$(<"$file")
|
||||||
|
|
||||||
|
|||||||
+21
-17
@@ -154,8 +154,8 @@ normalizeSize() {
|
|||||||
local diskDesc="$2"
|
local diskDesc="$2"
|
||||||
local dir="$3"
|
local dir="$3"
|
||||||
|
|
||||||
local gb free space
|
local free dataSize
|
||||||
local dataSize spare=1073741824
|
local spare=1073741824
|
||||||
|
|
||||||
if [[ "${diskSpace,,}" == "max" || "${diskSpace,,}" == "half" ]]; then
|
if [[ "${diskSpace,,}" == "max" || "${diskSpace,,}" == "half" ]]; then
|
||||||
|
|
||||||
@@ -168,12 +168,12 @@ normalizeSize() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
(( free < spare )) && free="$spare"
|
(( free < spare )) && free="$spare"
|
||||||
gb=$(( free / 1073741825 ))
|
local gb=$(( free / 1073741825 ))
|
||||||
diskSpace="${gb}G"
|
diskSpace="${gb}G"
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
space="${diskSpace// /}"
|
local space="${diskSpace// /}"
|
||||||
[ -z "$space" ] && space="256G"
|
[ -z "$space" ] && space="256G"
|
||||||
[ -z "${space//[0-9. ]}" ] && space="${space}G"
|
[ -z "${space//[0-9. ]}" ] && space="${space}G"
|
||||||
space=$(echo "${space^^}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
|
space=$(echo "${space^^}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
|
||||||
@@ -573,13 +573,12 @@ addDisk () {
|
|||||||
local diskCache="$9"
|
local diskCache="$9"
|
||||||
|
|
||||||
local fs dir used space
|
local fs dir used space
|
||||||
local diskExt diskFile
|
local diskExt dataSize
|
||||||
local dataSize missing
|
|
||||||
local available currentSize
|
local available currentSize
|
||||||
local previousExt previousFmt
|
local previousExt
|
||||||
|
|
||||||
diskExt=$(fmt2ext "$diskFmt")
|
diskExt=$(fmt2ext "$diskFmt")
|
||||||
diskFile="$diskBase.$diskExt"
|
local diskFile="$diskBase.$diskExt"
|
||||||
|
|
||||||
dir=$(dirname "$diskFile")
|
dir=$(dirname "$diskFile")
|
||||||
[ ! -d "$dir" ] && return 0
|
[ ! -d "$dir" ] && return 0
|
||||||
@@ -587,7 +586,11 @@ addDisk () {
|
|||||||
space=$(normalizeSize "$diskSpace" "$diskDesc" "$dir")
|
space=$(normalizeSize "$diskSpace" "$diskDesc" "$dir")
|
||||||
dataSize=$(numfmt --from=iec "$space")
|
dataSize=$(numfmt --from=iec "$space")
|
||||||
|
|
||||||
fs=$(stat -f -c %T "$dir")
|
if ! fs=$(stat -f -c %T "$dir"); then
|
||||||
|
error "Failed to determine filesystem type of \"$dir\" !"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
checkFS "$fs" "$diskFile" "$diskDesc" || exit $?
|
checkFS "$fs" "$diskFile" "$diskDesc" || exit $?
|
||||||
|
|
||||||
if ! supportsDirect "$fs"; then
|
if ! supportsDirect "$fs"; then
|
||||||
@@ -595,23 +598,24 @@ addDisk () {
|
|||||||
diskCache="writeback"
|
diskCache="writeback"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -s "$diskFile" ] ; then
|
if [ ! -f "$diskFile" ] || [ ! -s "$diskFile" ]; then
|
||||||
|
|
||||||
if [[ "${diskFmt,,}" != "raw" ]]; then
|
if [[ "${diskFmt,,}" != "raw" ]]; then
|
||||||
previousFmt="raw"
|
local previousFmt="raw"
|
||||||
else
|
else
|
||||||
previousFmt="qcow2"
|
local previousFmt="qcow2"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
previousExt=$(fmt2ext "$previousFmt")
|
previousExt=$(fmt2ext "$previousFmt")
|
||||||
|
|
||||||
if [ -s "$diskBase.$previousExt" ] ; then
|
if [ -f "$diskBase.$previousExt" ] &&
|
||||||
|
[ -s "$diskBase.$previousExt" ]; then
|
||||||
convertDisk "$diskBase.$previousExt" "$previousFmt" "$diskFile" "$diskFmt" "$diskBase" "$diskDesc" "$fs" || exit $?
|
convertDisk "$diskBase.$previousExt" "$previousFmt" "$diskFile" "$diskFmt" "$diskBase" "$diskDesc" "$fs" || exit $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -s "$diskFile" ]; then
|
if [ -f "$diskFile" ] && [ -s "$diskFile" ]; then
|
||||||
|
|
||||||
currentSize=$(getSize "$diskFile") || exit 71
|
currentSize=$(getSize "$diskFile") || exit 71
|
||||||
|
|
||||||
@@ -641,18 +645,18 @@ addDisk () {
|
|||||||
currentSize=$(getSize "$diskFile") || exit 73
|
currentSize=$(getSize "$diskFile") || exit 73
|
||||||
used=$(du -sB 1 "$diskFile" | cut -f1)
|
used=$(du -sB 1 "$diskFile" | cut -f1)
|
||||||
available=$(df --output=avail -B 1 "$dir" | tail -n 1)
|
available=$(df --output=avail -B 1 "$dir" | tail -n 1)
|
||||||
missing=$(( currentSize - used - available ))
|
local missing=$(( currentSize - used - available ))
|
||||||
(( missing < 0 )) && missing=0
|
(( missing < 0 )) && missing=0
|
||||||
|
|
||||||
if (( missing > 0 )); then
|
if (( missing > 0 )); then
|
||||||
|
|
||||||
local gb base msg
|
local gb base
|
||||||
|
|
||||||
gb=$(formatBytes "$available")
|
gb=$(formatBytes "$available")
|
||||||
base=$(baseDir "$dir")
|
base=$(baseDir "$dir")
|
||||||
missing=$(formatBytes "$missing")
|
missing=$(formatBytes "$missing")
|
||||||
currentSize=$(formatBytes "$currentSize")
|
currentSize=$(formatBytes "$currentSize")
|
||||||
msg="The virtual size of the ${diskDesc,,} is $currentSize"
|
local msg="The virtual size of the ${diskDesc,,} is $currentSize"
|
||||||
|
|
||||||
if [ -n "$used" ] && [[ "$used" != "0" ]]; then
|
if [ -n "$used" ] && [[ "$used" != "0" ]]; then
|
||||||
used=$(formatBytes "$used")
|
used=$(formatBytes "$used")
|
||||||
|
|||||||
+191
-90
@@ -84,8 +84,7 @@ getMTU() {
|
|||||||
|
|
||||||
minMTU() {
|
minMTU() {
|
||||||
|
|
||||||
local mtu=""
|
local mtu min=""
|
||||||
local min=""
|
|
||||||
|
|
||||||
for mtu in "$@"; do
|
for mtu in "$@"; do
|
||||||
[[ -z "$mtu" || "$mtu" == "0" ]] && continue
|
[[ -z "$mtu" || "$mtu" == "0" ]] && continue
|
||||||
@@ -124,7 +123,7 @@ gatewayMAC() {
|
|||||||
maskToCIDR() {
|
maskToCIDR() {
|
||||||
|
|
||||||
local mask="$1"
|
local mask="$1"
|
||||||
local prefix=""
|
local prefix
|
||||||
|
|
||||||
if ! command -v ipcalc > /dev/null 2>&1; then
|
if ! command -v ipcalc > /dev/null 2>&1; then
|
||||||
error "Required command 'ipcalc' is not installed!"
|
error "Required command 'ipcalc' is not installed!"
|
||||||
@@ -154,7 +153,7 @@ maskToCIDR() {
|
|||||||
networkCIDR() {
|
networkCIDR() {
|
||||||
|
|
||||||
local ip="$1"
|
local ip="$1"
|
||||||
local network=""
|
local network
|
||||||
|
|
||||||
network=$(ipcalc -n -b "$ip/$MASK" 2>/dev/null | awk '
|
network=$(ipcalc -n -b "$ip/$MASK" 2>/dev/null | awk '
|
||||||
/^Network:/ {
|
/^Network:/ {
|
||||||
@@ -172,6 +171,37 @@ networkCIDR() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
upstreamIP() {
|
||||||
|
|
||||||
|
local subnet="$1"
|
||||||
|
local guest="$2"
|
||||||
|
local gateway="$3"
|
||||||
|
local broadcast candidate last
|
||||||
|
|
||||||
|
broadcast=$(ipcalc -n -b "$subnet" 2>/dev/null | awk '
|
||||||
|
/^Broadcast:/ {
|
||||||
|
print $2
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
')
|
||||||
|
|
||||||
|
if [[ ! "$broadcast" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
last="${broadcast##*.}"
|
||||||
|
|
||||||
|
for (( last--; last>=2; last-- )); do
|
||||||
|
candidate="${broadcast%.*}.$last"
|
||||||
|
[[ "$candidate" == "$guest" || "$candidate" == "$gateway" ]] && continue
|
||||||
|
|
||||||
|
echo "$candidate"
|
||||||
|
return 0
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
detectInterface() {
|
detectInterface() {
|
||||||
|
|
||||||
if [ -n "$DEV" ]; then
|
if [ -n "$DEV" ]; then
|
||||||
@@ -207,16 +237,23 @@ formatAddress() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultGateway() {
|
||||||
|
|
||||||
|
ip -4 route list default dev "$1" 2>/dev/null |
|
||||||
|
awk '$1 == "default" { for (i = 1; i < NF; i++) if ($i == "via") { print $(i + 1); exit } }' || :
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
detectAddresses() {
|
detectAddresses() {
|
||||||
|
|
||||||
GATEWAY=$(ip route list dev "$DEV" | awk ' /^default/ {print $3}' | head -n 1)
|
GATEWAY=$(defaultGateway "$DEV")
|
||||||
{ UPLINK=$(ip address show dev "$DEV" | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/ | head -n 1); } 2>/dev/null || :
|
{ UPLINK=$(ip address show dev "$DEV" | grep inet | awk '/inet / { print $2 }' | cut -f1 -d/ | head -n 1); } 2>/dev/null || :
|
||||||
|
|
||||||
IP6=""
|
IP6=""
|
||||||
|
|
||||||
if [ -f /proc/net/if_inet6 ] && [[ "$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null)" != "1" ]]; then
|
if [ -f /proc/net/if_inet6 ] && [[ "$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null)" != "1" ]]; then
|
||||||
local rc=0
|
{ IP6=$(ip -6 addr show dev "$DEV" scope global up); local rc=$?; } 2>/dev/null || :
|
||||||
{ IP6=$(ip -6 addr show dev "$DEV" scope global up); rc=$?; } 2>/dev/null || :
|
|
||||||
(( rc != 0 )) && IP6=""
|
(( rc != 0 )) && IP6=""
|
||||||
[ -n "$IP6" ] && IP6=$(echo "$IP6" | sed -e's/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d' | head -n 1)
|
[ -n "$IP6" ] && IP6=$(echo "$IP6" | sed -e's/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d' | head -n 1)
|
||||||
fi
|
fi
|
||||||
@@ -226,7 +263,7 @@ detectAddresses() {
|
|||||||
|
|
||||||
detectAdapter() {
|
detectAdapter() {
|
||||||
|
|
||||||
local result=""
|
local result
|
||||||
|
|
||||||
NIC=""
|
NIC=""
|
||||||
BUS=""
|
BUS=""
|
||||||
@@ -252,7 +289,7 @@ detectAdapter() {
|
|||||||
|
|
||||||
containerID() {
|
containerID() {
|
||||||
|
|
||||||
local id=""
|
local id
|
||||||
|
|
||||||
id=$(hostname -s 2>/dev/null || true)
|
id=$(hostname -s 2>/dev/null || true)
|
||||||
|
|
||||||
@@ -260,7 +297,7 @@ containerID() {
|
|||||||
id=$(< /etc/machine-id)
|
id=$(< /etc/machine-id)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$id" ] && [ -s /proc/sys/kernel/random/boot_id ]; then
|
if [ -z "$id" ] && [ -r /proc/sys/kernel/random/boot_id ]; then
|
||||||
id=$(< /proc/sys/kernel/random/boot_id)
|
id=$(< /proc/sys/kernel/random/boot_id)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -286,7 +323,7 @@ disableIPv6() {
|
|||||||
subnetInUse() {
|
subnetInUse() {
|
||||||
|
|
||||||
local subnet="$1"
|
local subnet="$1"
|
||||||
local broader="" narrower="" routes=""
|
local broader narrower routes
|
||||||
|
|
||||||
if ! broader=$(ip -4 route show table all match "$subnet" 2>/dev/null); then
|
if ! broader=$(ip -4 route show table all match "$subnet" 2>/dev/null); then
|
||||||
error "Failed to inspect existing routes for subnet $subnet."
|
error "Failed to inspect existing routes for subnet $subnet."
|
||||||
@@ -324,15 +361,14 @@ guestIP() {
|
|||||||
natGuestIP() {
|
natGuestIP() {
|
||||||
|
|
||||||
local ip="$1"
|
local ip="$1"
|
||||||
local start="" guest="" subnet=""
|
local guest subnet second third
|
||||||
local second="" third="" rc=""
|
|
||||||
|
|
||||||
third=$(cut -d. -f3 <<< "$ip")
|
third=$(cut -d. -f3 <<< "$ip")
|
||||||
|
|
||||||
if [[ "$ip" == "172.30."* ]]; then
|
if [[ "$ip" == "172.30."* ]]; then
|
||||||
start="31"
|
local start="31"
|
||||||
else
|
else
|
||||||
start="30"
|
local start="30"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for (( second=start; second<=254; second++ )); do
|
for (( second=start; second<=254; second++ )); do
|
||||||
@@ -342,7 +378,7 @@ natGuestIP() {
|
|||||||
if subnetInUse "$subnet"; then
|
if subnetInUse "$subnet"; then
|
||||||
continue
|
continue
|
||||||
else
|
else
|
||||||
rc=$?
|
local rc=$?
|
||||||
(( rc == 1 )) || return 1
|
(( rc == 1 )) || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -357,7 +393,7 @@ natGuestIP() {
|
|||||||
if subnetInUse "$subnet"; then
|
if subnetInUse "$subnet"; then
|
||||||
continue
|
continue
|
||||||
else
|
else
|
||||||
rc=$?
|
local rc=$?
|
||||||
(( rc == 1 )) || return 1
|
(( rc == 1 )) || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -411,7 +447,8 @@ configureDNS() {
|
|||||||
local host="$4"
|
local host="$4"
|
||||||
local mask="$5"
|
local mask="$5"
|
||||||
local gateway="$6"
|
local gateway="$6"
|
||||||
local arguments="$DNSMASQ_OPTS" rc
|
local upstream="${7:-}"
|
||||||
|
local arguments="$DNSMASQ_OPTS"
|
||||||
|
|
||||||
if ! echo "$gateway" > /run/shm/qemu.gw; then
|
if ! echo "$gateway" > /run/shm/qemu.gw; then
|
||||||
error "Failed to write gateway file."
|
error "Failed to write gateway file."
|
||||||
@@ -459,6 +496,11 @@ configureDNS() {
|
|||||||
# Add DNS entry for container
|
# Add DNS entry for container
|
||||||
arguments+=" --address=/host.lan/$gateway"
|
arguments+=" --address=/host.lan/$gateway"
|
||||||
|
|
||||||
|
# Add DNS entry for the upstream gateway.
|
||||||
|
if isNAT && [ -n "$upstream" ]; then
|
||||||
|
arguments+=" --address=/system.lan/$upstream"
|
||||||
|
fi
|
||||||
|
|
||||||
# Avoid returning IPv6 records when the active network mode is IPv4-only.
|
# Avoid returning IPv6 records when the active network mode is IPv4-only.
|
||||||
if isNAT || [ -z "$IP6" ]; then
|
if isNAT || [ -z "$IP6" ]; then
|
||||||
arguments+=" --filter-AAAA"
|
arguments+=" --filter-AAAA"
|
||||||
@@ -478,7 +520,7 @@ configureDNS() {
|
|||||||
arguments=$(echo "$arguments" | sed 's/\t/ /g' | tr -s ' ' | sed 's/^ *//')
|
arguments=$(echo "$arguments" | sed 's/\t/ /g' | tr -s ' ' | sed 's/^ *//')
|
||||||
enabled "$DEBUG" && printf "Dnsmasq arguments:\n\n%s\n\n" "${arguments// -/$'\n-'}"
|
enabled "$DEBUG" && printf "Dnsmasq arguments:\n\n%s\n\n" "${arguments// -/$'\n-'}"
|
||||||
|
|
||||||
{ $DNSMASQ ${arguments:+ $arguments}; rc=$?; } || :
|
{ $DNSMASQ ${arguments:+ $arguments}; local rc=$?; } || :
|
||||||
|
|
||||||
if (( rc != 0 )); then
|
if (( rc != 0 )); then
|
||||||
|
|
||||||
@@ -501,9 +543,9 @@ configureDNS() {
|
|||||||
|
|
||||||
getHostPorts() {
|
getHostPorts() {
|
||||||
|
|
||||||
local port="" ports=""
|
|
||||||
local num="" mode="${1:-tcp}"
|
|
||||||
local list="${HOST_PORTS// /},"
|
local list="${HOST_PORTS// /},"
|
||||||
|
local port ports=""
|
||||||
|
local mode="${1:-tcp}"
|
||||||
|
|
||||||
for port in ${list//,/ }; do
|
for port in ${list//,/ }; do
|
||||||
|
|
||||||
@@ -512,14 +554,14 @@ getHostPorts() {
|
|||||||
case "$mode" in
|
case "$mode" in
|
||||||
"tcp" )
|
"tcp" )
|
||||||
[[ "$port" == *"/udp" ]] && continue
|
[[ "$port" == *"/udp" ]] && continue
|
||||||
num="${port%/tcp}"
|
local num="${port%/tcp}"
|
||||||
;;
|
;;
|
||||||
"all" )
|
"all" )
|
||||||
if [[ "$port" == *"/udp" ]]; then
|
if [[ "$port" == *"/udp" ]]; then
|
||||||
num="${port%/udp}"
|
local num="${port%/udp}"
|
||||||
[ -n "$num" ] && ports+="$num/udp,"
|
[ -n "$num" ] && ports+="$num/udp,"
|
||||||
else
|
else
|
||||||
num="${port%/tcp}"
|
local num="${port%/tcp}"
|
||||||
[ -n "$num" ] && ports+="$num/tcp,"
|
[ -n "$num" ] && ports+="$num/tcp,"
|
||||||
fi
|
fi
|
||||||
continue
|
continue
|
||||||
@@ -545,16 +587,15 @@ getUserPorts() {
|
|||||||
local defaults="22/tcp,5000/tcp,5001/tcp"
|
local defaults="22/tcp,5000/tcp,5001/tcp"
|
||||||
local list="$defaults,${USER_PORTS// /},"
|
local list="$defaults,${USER_PORTS// /},"
|
||||||
|
|
||||||
local num="" ports="" proto=""
|
local ports=""
|
||||||
local userport="" hostport=""
|
local userport hostport exclude
|
||||||
|
|
||||||
local exclude=""
|
|
||||||
exclude=$(getHostPorts "all")
|
exclude=$(getHostPorts "all")
|
||||||
|
|
||||||
for userport in ${list//,/ }; do
|
for userport in ${list//,/ }; do
|
||||||
|
|
||||||
proto="tcp"
|
local proto="tcp"
|
||||||
num="$userport"
|
local num="$userport"
|
||||||
|
|
||||||
if [[ "$userport" == *"/udp" ]]; then
|
if [[ "$userport" == *"/udp" ]]; then
|
||||||
proto="udp"
|
proto="udp"
|
||||||
@@ -593,7 +634,7 @@ getUserPorts() {
|
|||||||
getSlirp() {
|
getSlirp() {
|
||||||
|
|
||||||
local ip="$1"
|
local ip="$1"
|
||||||
local args="" list=""
|
local args="" list
|
||||||
|
|
||||||
list=$(getUserPorts)
|
list=$(getUserPorts)
|
||||||
|
|
||||||
@@ -617,9 +658,9 @@ getSlirp() {
|
|||||||
|
|
||||||
getPasst() {
|
getPasst() {
|
||||||
|
|
||||||
local args="" list="" port=""
|
local list port
|
||||||
local num="" tcp="" udp=""
|
|
||||||
local bind="$UPLINK"
|
local bind="$UPLINK"
|
||||||
|
local tcp="" udp="" args=""
|
||||||
|
|
||||||
list=$(getUserPorts)
|
list=$(getUserPorts)
|
||||||
|
|
||||||
@@ -629,12 +670,12 @@ getPasst() {
|
|||||||
|
|
||||||
if [[ "$port" == *"/udp" ]]; then
|
if [[ "$port" == *"/udp" ]]; then
|
||||||
|
|
||||||
num="${port%/udp}"
|
local num="${port%/udp}"
|
||||||
[ -n "$num" ] && udp+="$num,"
|
[ -n "$num" ] && udp+="$num,"
|
||||||
|
|
||||||
elif [[ "$port" == *"/tcp" ]]; then
|
elif [[ "$port" == *"/tcp" ]]; then
|
||||||
|
|
||||||
num="${port%/tcp}"
|
local num="${port%/tcp}"
|
||||||
[ -n "$num" ] && tcp+="$num,"
|
[ -n "$num" ] && tcp+="$num,"
|
||||||
|
|
||||||
else
|
else
|
||||||
@@ -665,8 +706,7 @@ getPasst() {
|
|||||||
|
|
||||||
configureVTAP() {
|
configureVTAP() {
|
||||||
|
|
||||||
local msg=""
|
local msg dev
|
||||||
local rc
|
|
||||||
|
|
||||||
enabled "$DEBUG" && echo "Configuring MACVTAP networking..."
|
enabled "$DEBUG" && echo "Configuring MACVTAP networking..."
|
||||||
|
|
||||||
@@ -678,7 +718,7 @@ configureVTAP() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Create a macvtap network for the VM guest
|
# Create a macvtap network for the VM guest
|
||||||
{ msg=$(ip link add link "$DEV" name "$TAP" address "$MAC" type macvtap mode bridge 2>&1); rc=$?; } || :
|
{ msg=$(ip link add link "$DEV" name "$TAP" address "$MAC" type macvtap mode bridge 2>&1); local rc=$?; } || :
|
||||||
|
|
||||||
case "$msg" in
|
case "$msg" in
|
||||||
"RTNETLINK answers: File exists"* )
|
"RTNETLINK answers: File exists"* )
|
||||||
@@ -711,15 +751,35 @@ configureVTAP() {
|
|||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
local TAP_NR TAP_PATH MAJOR MINOR
|
local TAP_NR MAJOR MINOR
|
||||||
TAP_NR=$(</sys/class/net/"$TAP"/ifindex)
|
|
||||||
TAP_PATH="/dev/tap${TAP_NR}"
|
if ! dev=$(cat /sys/devices/virtual/net/"$TAP"/tap*/dev); then
|
||||||
|
error "Failed to determine device numbers for MACVTAP interface \"$TAP\" !"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
IFS=: read -r MAJOR MINOR <<< "$dev"
|
||||||
|
|
||||||
|
if [[ ! "$MAJOR" =~ ^[0-9]+$ || ! "$MINOR" =~ ^[0-9]+$ ]]; then
|
||||||
|
error "Failed to parse device numbers for MACVTAP interface \"$TAP\" !"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( MAJOR < 1 )); then
|
||||||
|
error "Cannot find: sys/devices/virtual/net/$TAP"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! TAP_NR=$(<"/sys/class/net/$TAP/ifindex"); then
|
||||||
|
error "Failed to determine interface index of MACVTAP interface \"$TAP\" !"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Create dev file (there is no udev in container: need to be done manually)
|
# Create dev file (there is no udev in container: need to be done manually)
|
||||||
IFS=: read -r MAJOR MINOR < <(cat /sys/devices/virtual/net/"$TAP"/tap*/dev)
|
local TAP_PATH="/dev/tap${TAP_NR}"
|
||||||
(( MAJOR < 1)) && error "Cannot find: sys/devices/virtual/net/$TAP" && return 1
|
|
||||||
|
|
||||||
[[ ! -e "$TAP_PATH" && -e "/dev0/${TAP_PATH##*/}" ]] && ln -s "/dev0/${TAP_PATH##*/}" "$TAP_PATH"
|
[[ ! -e "$TAP_PATH" && -e "/dev0/${TAP_PATH##*/}" ]] &&
|
||||||
|
ln -s "/dev0/${TAP_PATH##*/}" "$TAP_PATH"
|
||||||
|
|
||||||
if [[ ! -e "$TAP_PATH" ]]; then
|
if [[ ! -e "$TAP_PATH" ]]; then
|
||||||
{ mknod "$TAP_PATH" c "$MAJOR" "$MINOR"; rc=$?; } || :
|
{ mknod "$TAP_PATH" c "$MAJOR" "$MINOR"; rc=$?; } || :
|
||||||
@@ -753,7 +813,7 @@ configureSlirp() {
|
|||||||
|
|
||||||
ip=$(guestIP "$ip" 4)
|
ip=$(guestIP "$ip" 4)
|
||||||
local gateway="${ip%.*}.1"
|
local gateway="${ip%.*}.1"
|
||||||
local subnet=""
|
local subnet
|
||||||
subnet=$(networkCIDR "$ip") || return 1
|
subnet=$(networkCIDR "$ip") || return 1
|
||||||
|
|
||||||
local ipv6="ipv6=off,"
|
local ipv6="ipv6=off,"
|
||||||
@@ -761,7 +821,7 @@ configureSlirp() {
|
|||||||
|
|
||||||
NET_OPTS="-netdev user,id=hostnet0,ipv4=on,host=$gateway,net=$subnet,dhcpstart=$ip,${ipv6}hostname=$HOST"
|
NET_OPTS="-netdev user,id=hostnet0,ipv4=on,host=$gateway,net=$subnet,dhcpstart=$ip,${ipv6}hostname=$HOST"
|
||||||
|
|
||||||
local forward=""
|
local forward
|
||||||
forward=$(getSlirp "$ip")
|
forward=$(getSlirp "$ip")
|
||||||
[ -n "$forward" ] && NET_OPTS+=",$forward"
|
[ -n "$forward" ] && NET_OPTS+=",$forward"
|
||||||
|
|
||||||
@@ -818,7 +878,7 @@ configurePasst() {
|
|||||||
# Pass an explicit MTU to passt.
|
# Pass an explicit MTU to passt.
|
||||||
PASST_OPTS+=" -m $passt_mtu"
|
PASST_OPTS+=" -m $passt_mtu"
|
||||||
|
|
||||||
local forward=""
|
local forward
|
||||||
forward=$(getPasst)
|
forward=$(getPasst)
|
||||||
[ -n "$forward" ] && PASST_OPTS+="$forward"
|
[ -n "$forward" ] && PASST_OPTS+="$forward"
|
||||||
|
|
||||||
@@ -854,11 +914,10 @@ configurePasst() {
|
|||||||
|
|
||||||
if ! "$PASST" ${PASST_OPTS:+$PASST_OPTS} >/dev/null 2>&1; then
|
if ! "$PASST" ${PASST_OPTS:+$PASST_OPTS} >/dev/null 2>&1; then
|
||||||
|
|
||||||
local rc=0
|
|
||||||
rm -f "$log"
|
rm -f "$log"
|
||||||
|
|
||||||
PASST_OPTS="${PASST_OPTS/ -q/}"
|
PASST_OPTS="${PASST_OPTS/ -q/}"
|
||||||
{ "$PASST" ${PASST_OPTS:+$PASST_OPTS}; rc=$?; } || :
|
{ "$PASST" ${PASST_OPTS:+$PASST_OPTS}; local rc=$?; } || :
|
||||||
|
|
||||||
if (( rc != 0 )); then
|
if (( rc != 0 )); then
|
||||||
[ -f "$log" ] && [ -s "$log" ] && cat "$log"
|
[ -f "$log" ] && [ -s "$log" ] && cat "$log"
|
||||||
@@ -889,10 +948,10 @@ configurePasst() {
|
|||||||
createBridge() {
|
createBridge() {
|
||||||
|
|
||||||
local gateway="$1"
|
local gateway="$1"
|
||||||
local rc msg=""
|
local msg
|
||||||
|
|
||||||
# Create a bridge with a static IP for the VM guest
|
# Create a bridge with a static IP for the VM guest
|
||||||
{ msg=$(ip link add dev "$BRIDGE" type bridge 2>&1); rc=$?; } || :
|
{ msg=$(ip link add dev "$BRIDGE" type bridge 2>&1); local rc=$?; } || :
|
||||||
|
|
||||||
if (( rc != 0 )); then
|
if (( rc != 0 )); then
|
||||||
enabled "$ROOTLESS" && ! enabled "$DEBUG" && return 1
|
enabled "$ROOTLESS" && ! enabled "$DEBUG" && return 1
|
||||||
@@ -930,10 +989,10 @@ createBridge() {
|
|||||||
createTap() {
|
createTap() {
|
||||||
|
|
||||||
local tuntap="$1"
|
local tuntap="$1"
|
||||||
local rc msg=""
|
local msg
|
||||||
|
|
||||||
# Set tap to the bridge created
|
# Set tap to the bridge created
|
||||||
{ msg=$(ip tuntap add dev "$TAP" mode tap 2>&1); rc=$?; } || :
|
{ msg=$(ip tuntap add dev "$TAP" mode tap 2>&1); local rc=$?; } || :
|
||||||
|
|
||||||
if (( rc != 0 )); then
|
if (( rc != 0 )); then
|
||||||
enabled "$ROOTLESS" && ! enabled "$DEBUG" && return 1
|
enabled "$ROOTLESS" && ! enabled "$DEBUG" && return 1
|
||||||
@@ -976,7 +1035,7 @@ hasTable() {
|
|||||||
|
|
||||||
getTablesBackend() {
|
getTablesBackend() {
|
||||||
|
|
||||||
local version=""
|
local version
|
||||||
version=$(iptables --version 2>/dev/null || true)
|
version=$(iptables --version 2>/dev/null || true)
|
||||||
|
|
||||||
case "$version" in
|
case "$version" in
|
||||||
@@ -989,7 +1048,7 @@ getTablesBackend() {
|
|||||||
setTables() {
|
setTables() {
|
||||||
|
|
||||||
local mode="$1"
|
local mode="$1"
|
||||||
local path=""
|
local path
|
||||||
|
|
||||||
path=$(command -v "iptables-$mode" 2>/dev/null || true)
|
path=$(command -v "iptables-$mode" 2>/dev/null || true)
|
||||||
[ -z "$path" ] && return 1
|
[ -z "$path" ] && return 1
|
||||||
@@ -1003,7 +1062,7 @@ showRules() {
|
|||||||
local chain="$2"
|
local chain="$2"
|
||||||
local label="$3"
|
local label="$3"
|
||||||
local rule_tag="$4"
|
local rule_tag="$4"
|
||||||
local rules=""
|
local rules
|
||||||
local own_rule="--comment[[:space:]]+\"?$rule_tag\"?([[:space:]]|\$)"
|
local own_rule="--comment[[:space:]]+\"?$rule_tag\"?([[:space:]]|\$)"
|
||||||
|
|
||||||
enabled "$DEBUG" || return 0
|
enabled "$DEBUG" || return 0
|
||||||
@@ -1022,7 +1081,7 @@ showRules() {
|
|||||||
|
|
||||||
checkExistingTables() {
|
checkExistingTables() {
|
||||||
|
|
||||||
local msg="" rules="" conflicts=""
|
local rules conflicts
|
||||||
local rule_tag="QEMU_DNAT"
|
local rule_tag="QEMU_DNAT"
|
||||||
local own_rule="--comment[[:space:]]+\"?$rule_tag\"?([[:space:]]|\$)"
|
local own_rule="--comment[[:space:]]+\"?$rule_tag\"?([[:space:]]|\$)"
|
||||||
|
|
||||||
@@ -1040,7 +1099,7 @@ checkExistingTables() {
|
|||||||
<<< "$rules" || true)
|
<<< "$rules" || true)
|
||||||
|
|
||||||
if [ -n "$conflicts" ]; then
|
if [ -n "$conflicts" ]; then
|
||||||
msg="your existing NAT rules may take precedence over VM port forwarding"
|
local msg="your existing NAT rules may take precedence over VM port forwarding"
|
||||||
|
|
||||||
if enabled "$DEBUG"; then
|
if enabled "$DEBUG"; then
|
||||||
warn "${msg}."
|
warn "${msg}."
|
||||||
@@ -1060,7 +1119,7 @@ checkExistingTables() {
|
|||||||
<<< "$rules" || true)
|
<<< "$rules" || true)
|
||||||
|
|
||||||
if [ -n "$conflicts" ]; then
|
if [ -n "$conflicts" ]; then
|
||||||
msg="your existing firewall rules may block traffic forwarded to or from the VM"
|
local msg="your existing firewall rules may block traffic forwarded to or from the VM"
|
||||||
|
|
||||||
if enabled "$DEBUG"; then
|
if enabled "$DEBUG"; then
|
||||||
warn "${msg}."
|
warn "${msg}."
|
||||||
@@ -1088,13 +1147,13 @@ runTableRule() {
|
|||||||
|
|
||||||
local silent="$1"
|
local silent="$1"
|
||||||
local result="$2"
|
local result="$2"
|
||||||
local rc msg=""
|
local msg
|
||||||
|
|
||||||
shift 2
|
shift 2
|
||||||
|
|
||||||
printf -v "$result" '%s' ""
|
printf -v "$result" '%s' ""
|
||||||
|
|
||||||
{ msg=$("$@" 2>&1); rc=$?; } || :
|
{ msg=$("$@" 2>&1); local rc=$?; } || :
|
||||||
(( rc == 0 )) && return 0
|
(( rc == 0 )) && return 0
|
||||||
|
|
||||||
printf -v "$result" '%s' "$msg"
|
printf -v "$result" '%s' "$msg"
|
||||||
@@ -1154,8 +1213,8 @@ applyTables() {
|
|||||||
local ip="$1"
|
local ip="$1"
|
||||||
local subnet="$2"
|
local subnet="$2"
|
||||||
local silent="${3:-N}"
|
local silent="${3:-N}"
|
||||||
local exclude="" port=""
|
local exclude port
|
||||||
local table_error=""
|
local table_error
|
||||||
local dnat_chain="QEMU_DNAT"
|
local dnat_chain="QEMU_DNAT"
|
||||||
local rule_tag="$dnat_chain"
|
local rule_tag="$dnat_chain"
|
||||||
|
|
||||||
@@ -1283,8 +1342,8 @@ applyTables() {
|
|||||||
|
|
||||||
clearTables() {
|
clearTables() {
|
||||||
|
|
||||||
local table="" line="" chain=""
|
local line
|
||||||
local rules="" remaining="" message=""
|
local rules remaining message
|
||||||
local dnat_chain="QEMU_DNAT"
|
local dnat_chain="QEMU_DNAT"
|
||||||
local rule_tag="$dnat_chain"
|
local rule_tag="$dnat_chain"
|
||||||
local own_rule="--comment[[:space:]]+\"?$rule_tag\"?([[:space:]]|\$)"
|
local own_rule="--comment[[:space:]]+\"?$rule_tag\"?([[:space:]]|\$)"
|
||||||
@@ -1309,15 +1368,15 @@ clearTables() {
|
|||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
|
|
||||||
case "$line" in
|
case "$line" in
|
||||||
\*nat ) table="nat" ;;
|
\*nat ) local table="nat" ;;
|
||||||
\*filter ) table="filter" ;;
|
\*filter ) local table="filter" ;;
|
||||||
\*mangle ) table="mangle" ;;
|
\*mangle ) local table="mangle" ;;
|
||||||
\*raw ) table="raw" ;;
|
\*raw ) local table="raw" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [[ "$line" == -A* ]] && [[ "$line" =~ $own_rule ]]; then
|
if [[ "$line" == -A* ]] && [[ "$line" =~ $own_rule ]]; then
|
||||||
|
|
||||||
chain="${line#-A }"
|
local chain="${line#-A }"
|
||||||
chain="${chain%% *}"
|
chain="${chain%% *}"
|
||||||
|
|
||||||
# Rules inside this chain are removed together by the flush below.
|
# Rules inside this chain are removed together by the flush below.
|
||||||
@@ -1383,7 +1442,7 @@ clearTables() {
|
|||||||
hasTaggedRules() {
|
hasTaggedRules() {
|
||||||
|
|
||||||
local save="$1"
|
local save="$1"
|
||||||
local rules=""
|
local rules
|
||||||
local dnat_chain="QEMU_DNAT"
|
local dnat_chain="QEMU_DNAT"
|
||||||
local rule_tag="$dnat_chain"
|
local rule_tag="$dnat_chain"
|
||||||
local own_rule="--comment[[:space:]]+\"?$rule_tag\"?([[:space:]]|\$)"
|
local own_rule="--comment[[:space:]]+\"?$rule_tag\"?([[:space:]]|\$)"
|
||||||
@@ -1405,9 +1464,8 @@ configureTables() {
|
|||||||
|
|
||||||
local ip="$1"
|
local ip="$1"
|
||||||
local subnet="$2"
|
local subnet="$2"
|
||||||
local preferred=""
|
local preferred
|
||||||
local alternate=""
|
local alternate_save
|
||||||
local alternate_save=""
|
|
||||||
local preferred_clean="N"
|
local preferred_clean="N"
|
||||||
local alternate_dirty="N"
|
local alternate_dirty="N"
|
||||||
|
|
||||||
@@ -1418,8 +1476,8 @@ configureTables() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "$preferred" in
|
case "$preferred" in
|
||||||
"nft" ) alternate="legacy" ;;
|
"nft" ) local alternate="legacy" ;;
|
||||||
"legacy" ) alternate="nft" ;;
|
"legacy" ) local alternate="nft" ;;
|
||||||
* )
|
* )
|
||||||
enabled "$ROOTLESS" && ! enabled "$DEBUG" && return 1
|
enabled "$ROOTLESS" && ! enabled "$DEBUG" && return 1
|
||||||
warn "unsupported IP tables backend: $preferred"
|
warn "unsupported IP tables backend: $preferred"
|
||||||
@@ -1605,10 +1663,46 @@ configureTables() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addUpstream() {
|
||||||
|
|
||||||
|
local upstream="$1"
|
||||||
|
local table_error
|
||||||
|
local rule_tag="QEMU_DNAT"
|
||||||
|
|
||||||
|
[ -n "$upstream" ] || return 1
|
||||||
|
[ -n "$GATEWAY" ] || return 1
|
||||||
|
|
||||||
|
if ! ip address add "$upstream/32" dev "$BRIDGE"; then
|
||||||
|
if ! enabled "$ROOTLESS" || enabled "$DEBUG"; then
|
||||||
|
warn "failed to add the system.lan address; access through that name will be unavailable."
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! runTableRule "Y" table_error \
|
||||||
|
iptables -t nat -A PREROUTING \
|
||||||
|
-i "$BRIDGE" \
|
||||||
|
-d "$upstream" \
|
||||||
|
-m comment --comment "$rule_tag" \
|
||||||
|
-j DNAT --to-destination "$GATEWAY"; then
|
||||||
|
|
||||||
|
ip address del "$upstream/32" dev "$BRIDGE" > /dev/null 2>&1 || :
|
||||||
|
|
||||||
|
if ! enabled "$ROOTLESS" || enabled "$DEBUG"; then
|
||||||
|
[ -n "$table_error" ] && echo "$table_error" >&2
|
||||||
|
warn "failed to configure system.lan forwarding; access through that name will be unavailable."
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
configureNAT() {
|
configureNAT() {
|
||||||
|
|
||||||
local tuntap="TUN device is missing. $ADD_ERR --device /dev/net/tun"
|
local tuntap="TUN device is missing. $ADD_ERR --device /dev/net/tun"
|
||||||
local rc ip subnet msg="" forwarding=""
|
local ip subnet upstream="" forwarding=""
|
||||||
|
|
||||||
enabled "$DEBUG" && echo "Configuring NAT networking..."
|
enabled "$DEBUG" && echo "Configuring NAT networking..."
|
||||||
|
|
||||||
@@ -1616,7 +1710,8 @@ configureNAT() {
|
|||||||
if [ ! -c /dev/net/tun ]; then
|
if [ ! -c /dev/net/tun ]; then
|
||||||
[ ! -d /dev/net ] && mkdir -m 755 /dev/net > /dev/null 2>&1 || :
|
[ ! -d /dev/net ] && mkdir -m 755 /dev/net > /dev/null 2>&1 || :
|
||||||
|
|
||||||
{ msg=$(mknod /dev/net/tun c 10 200 2>&1); rc=$?; } || :
|
local msg
|
||||||
|
{ msg=$(mknod /dev/net/tun c 10 200 2>&1); local rc=$?; } || :
|
||||||
|
|
||||||
if (( rc == 0 )); then
|
if (( rc == 0 )); then
|
||||||
chmod 666 /dev/net/tun
|
chmod 666 /dev/net/tun
|
||||||
@@ -1635,7 +1730,7 @@ configureNAT() {
|
|||||||
forwarding=$(< /proc/sys/net/ipv4/ip_forward)
|
forwarding=$(< /proc/sys/net/ipv4/ip_forward)
|
||||||
|
|
||||||
if [[ "$forwarding" != "1" ]]; then
|
if [[ "$forwarding" != "1" ]]; then
|
||||||
{ sysctl -w net.ipv4.ip_forward=1 > /dev/null 2>&1; rc=$?; } || :
|
{ sysctl -w net.ipv4.ip_forward=1 > /dev/null 2>&1; local rc=$?; } || :
|
||||||
|
|
||||||
forwarding=""
|
forwarding=""
|
||||||
[ -r /proc/sys/net/ipv4/ip_forward ] &&
|
[ -r /proc/sys/net/ipv4/ip_forward ] &&
|
||||||
@@ -1657,11 +1752,15 @@ configureNAT() {
|
|||||||
local gateway="${ip%.*}.1"
|
local gateway="${ip%.*}.1"
|
||||||
subnet=$(networkCIDR "$ip") || return 1
|
subnet=$(networkCIDR "$ip") || return 1
|
||||||
|
|
||||||
|
if [ -n "$GATEWAY" ]; then
|
||||||
|
upstream=$(upstreamIP "$subnet" "$ip" "$gateway") || upstream=""
|
||||||
|
fi
|
||||||
|
|
||||||
if subnetInUse "$subnet"; then
|
if subnetInUse "$subnet"; then
|
||||||
error "VM subnet $subnet conflicts with an existing route inside the container."
|
error "VM subnet $subnet conflicts with an existing route inside the container."
|
||||||
return 1
|
return 1
|
||||||
else
|
else
|
||||||
rc=$?
|
local rc=$?
|
||||||
(( rc == 1 )) || return 1
|
(( rc == 1 )) || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1675,16 +1774,20 @@ configureNAT() {
|
|||||||
|
|
||||||
configureTables "$ip" "$subnet" || return 1
|
configureTables "$ip" "$subnet" || return 1
|
||||||
|
|
||||||
|
if [ -n "$upstream" ] && ! addUpstream "$upstream"; then
|
||||||
|
upstream=""
|
||||||
|
fi
|
||||||
|
|
||||||
NET_OPTS="-netdev tap,id=hostnet0,ifname=$TAP"
|
NET_OPTS="-netdev tap,id=hostnet0,ifname=$TAP"
|
||||||
|
|
||||||
if [ -c /dev/vhost-net ]; then
|
if [ -c /dev/vhost-net ]; then
|
||||||
{ exec 40>>/dev/vhost-net; rc=$?; } 2>/dev/null || :
|
{ exec 40>>/dev/vhost-net; local rc=$?; } 2>/dev/null || :
|
||||||
(( rc == 0 )) && NET_OPTS+=",vhost=on,vhostfd=40"
|
(( rc == 0 )) && NET_OPTS+=",vhost=on,vhostfd=40"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
NET_OPTS+=",script=no,downscript=no"
|
NET_OPTS+=",script=no,downscript=no"
|
||||||
|
|
||||||
configureDNS "$BRIDGE" "$ip" "$MAC" "$HOST" "$MASK" "$gateway" || return 1
|
configureDNS "$BRIDGE" "$ip" "$MAC" "$HOST" "$MASK" "$gateway" "$upstream" || return 1
|
||||||
|
|
||||||
IP="$ip"
|
IP="$ip"
|
||||||
return 0
|
return 0
|
||||||
@@ -1740,7 +1843,7 @@ closeNetwork() {
|
|||||||
checkOS() {
|
checkOS() {
|
||||||
|
|
||||||
local iface="macvlan"
|
local iface="macvlan"
|
||||||
local os="" kernel=""
|
local os="" kernel
|
||||||
|
|
||||||
kernel=$(uname -a)
|
kernel=$(uname -a)
|
||||||
|
|
||||||
@@ -1891,14 +1994,12 @@ configureMTU() {
|
|||||||
|
|
||||||
configureMAC() {
|
configureMAC() {
|
||||||
|
|
||||||
local container=""
|
local container
|
||||||
local file=""
|
|
||||||
|
|
||||||
container=$(containerID)
|
container=$(containerID)
|
||||||
|
|
||||||
if [ -z "$MAC" ]; then
|
if [ -z "$MAC" ]; then
|
||||||
|
|
||||||
file="$STORAGE/dsm.mac"
|
local file="$STORAGE/dsm.mac"
|
||||||
|
|
||||||
if [ -s "$file" ]; then
|
if [ -s "$file" ]; then
|
||||||
if ! MAC=$(readFile "$file"); then
|
if ! MAC=$(readFile "$file"); then
|
||||||
@@ -1941,7 +2042,7 @@ configureMAC() {
|
|||||||
|
|
||||||
showHostInfo() {
|
showHostInfo() {
|
||||||
|
|
||||||
local mtu="" host="" uplink="" prefix=""
|
local mtu host uplink prefix
|
||||||
|
|
||||||
prefix=$(ip -4 -o address show dev "$DEV" scope global 2>/dev/null |
|
prefix=$(ip -4 -o address show dev "$DEV" scope global 2>/dev/null |
|
||||||
awk -v ip="$UPLINK" '
|
awk -v ip="$UPLINK" '
|
||||||
@@ -2028,10 +2129,10 @@ showGuestInfo() {
|
|||||||
|
|
||||||
local mode="${NETWORK,,}"
|
local mode="${NETWORK,,}"
|
||||||
|
|
||||||
if isNAT; then
|
if enabled "$DHCP"; then
|
||||||
mode="NAT"
|
|
||||||
elif enabled "$DHCP"; then
|
|
||||||
mode="DHCP"
|
mode="DHCP"
|
||||||
|
elif isNAT; then
|
||||||
|
mode="NAT"
|
||||||
elif isUserMode; then
|
elif isUserMode; then
|
||||||
mode="User ($mode)"
|
mode="User ($mode)"
|
||||||
elif [ -z "$mode" ]; then
|
elif [ -z "$mode" ]; then
|
||||||
|
|||||||
+8
-8
@@ -92,7 +92,7 @@ qemuPidFile() {
|
|||||||
waitQemuExit() {
|
waitQemuExit() {
|
||||||
|
|
||||||
local timeout="${1:-10}"
|
local timeout="${1:-10}"
|
||||||
local file=""
|
local file
|
||||||
|
|
||||||
qemuPidFile file
|
qemuPidFile file
|
||||||
waitPidFile "$file" "$timeout"
|
waitPidFile "$file" "$timeout"
|
||||||
@@ -101,7 +101,7 @@ waitQemuExit() {
|
|||||||
waitQemuPid() {
|
waitQemuPid() {
|
||||||
|
|
||||||
local -n _pid="$1"
|
local -n _pid="$1"
|
||||||
local cnt=0 value=""
|
local cnt=0 value
|
||||||
|
|
||||||
while ! readQemuPid value; do
|
while ! readQemuPid value; do
|
||||||
sleep 0.02
|
sleep 0.02
|
||||||
@@ -116,7 +116,7 @@ waitQemuPid() {
|
|||||||
forceKillQemu() {
|
forceKillQemu() {
|
||||||
|
|
||||||
local reason="$1"
|
local reason="$1"
|
||||||
local pid="" display
|
local pid display
|
||||||
|
|
||||||
! readQemuPid pid && return 0
|
! readQemuPid pid && return 0
|
||||||
! isAlive "$pid" && return 0
|
! isAlive "$pid" && return 0
|
||||||
@@ -145,7 +145,7 @@ cleanupHelpers() {
|
|||||||
startConsole() {
|
startConsole() {
|
||||||
|
|
||||||
local output="${1:-/dev/tty}"
|
local output="${1:-/dev/tty}"
|
||||||
local cnt=0 pid=""
|
local cnt=0
|
||||||
|
|
||||||
rm -f -- "$CONSOLE_SOCKET" "$CONSOLE_PID"
|
rm -f -- "$CONSOLE_SOCKET" "$CONSOLE_PID"
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ startConsole() {
|
|||||||
exec nc -lU "$CONSOLE_SOCKET" </dev/tty >"$output"
|
exec nc -lU "$CONSOLE_SOCKET" </dev/tty >"$output"
|
||||||
) &
|
) &
|
||||||
|
|
||||||
pid=$!
|
local pid="$!"
|
||||||
echo "$pid" > "$CONSOLE_PID"
|
echo "$pid" > "$CONSOLE_PID"
|
||||||
|
|
||||||
while [ ! -S "$CONSOLE_SOCKET" ]; do
|
while [ ! -S "$CONSOLE_SOCKET" ]; do
|
||||||
@@ -246,14 +246,14 @@ finish() {
|
|||||||
sendGuestShutdown() {
|
sendGuestShutdown() {
|
||||||
|
|
||||||
local pid="$1"
|
local pid="$1"
|
||||||
local response url
|
local response
|
||||||
|
|
||||||
# Don't send the powerdown signal because vDSM ignores ACPI signals
|
# Don't send the powerdown signal because vDSM ignores ACPI signals
|
||||||
# nc -q 1 -w 1 -U "$QEMU_DIR/monitor.sock" &> /dev/null <<<'system_powerdown' || :
|
# nc -q 1 -w 1 -U "$QEMU_DIR/monitor.sock" &> /dev/null <<<'system_powerdown' || :
|
||||||
|
|
||||||
# Send shutdown command to guest agent via serial port
|
# Send shutdown command to guest agent via serial port
|
||||||
API_TIMEOUT=$(strip "$API_TIMEOUT")
|
API_TIMEOUT=$(strip "$API_TIMEOUT")
|
||||||
url="http://localhost/read?command=$API_CMD&timeout=$API_TIMEOUT"
|
local url="http://localhost/read?command=$API_CMD&timeout=$API_TIMEOUT"
|
||||||
response=$(curl --unix-socket "$HOST_API_SOCKET" -sk -m "$(( API_TIMEOUT+2 ))" -S "$url" 2>&1)
|
response=$(curl --unix-socket "$HOST_API_SOCKET" -sk -m "$(( API_TIMEOUT+2 ))" -S "$url" 2>&1)
|
||||||
|
|
||||||
if [[ "$response" =~ "\"success\"" ]]; then
|
if [[ "$response" =~ "\"success\"" ]]; then
|
||||||
@@ -338,7 +338,7 @@ waitForShutdown() {
|
|||||||
graceful_shutdown() {
|
graceful_shutdown() {
|
||||||
|
|
||||||
local sig="$1"
|
local sig="$1"
|
||||||
local pid="" code=0
|
local pid code
|
||||||
|
|
||||||
[[ $BASHPID != "$TRAP_PID" ]] && return
|
[[ $BASHPID != "$TRAP_PID" ]] && return
|
||||||
|
|
||||||
|
|||||||
+27
-13
@@ -9,6 +9,7 @@ cd /run
|
|||||||
. utils.sh # Load functions
|
. utils.sh # Load functions
|
||||||
|
|
||||||
info () { printf "%b%s%b" "\E[1;34m❯ \E[1;36m" "$1" "\E[0m\n" >&2; }
|
info () { printf "%b%s%b" "\E[1;34m❯ \E[1;36m" "$1" "\E[0m\n" >&2; }
|
||||||
|
warn () { printf "%b%s%b" "\E[1;33m❯ " "WARNING: $1" "\E[0m\n" >&2; }
|
||||||
error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: $1" "\E[0m\n" >&2; }
|
error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: $1" "\E[0m\n" >&2; }
|
||||||
|
|
||||||
disabled "$NETWORK" && exit 0
|
disabled "$NETWORK" && exit 0
|
||||||
@@ -36,9 +37,7 @@ exitIfShuttingDown() {
|
|||||||
|
|
||||||
queryGuest() {
|
queryGuest() {
|
||||||
|
|
||||||
local rc
|
{ json=$(curl --unix-socket "$socket" -m 20 -sk "$url"); local rc=$?; } || :
|
||||||
|
|
||||||
{ json=$(curl --unix-socket "$socket" -m 20 -sk "$url"); rc=$?; } || :
|
|
||||||
|
|
||||||
exitIfShuttingDown
|
exitIfShuttingDown
|
||||||
|
|
||||||
@@ -54,9 +53,8 @@ readJsonField() {
|
|||||||
|
|
||||||
local query="$1"
|
local query="$1"
|
||||||
local result
|
local result
|
||||||
local rc
|
|
||||||
|
|
||||||
{ result=$(jq -r "$query" <<< "$json"); rc=$?; } || :
|
{ result=$(jq -r "$query" <<< "$json"); local rc=$?; } || :
|
||||||
|
|
||||||
if (( rc != 0 )); then
|
if (( rc != 0 )); then
|
||||||
error "$jq_err $rc ( $json )"
|
error "$jq_err $rc ( $json )"
|
||||||
@@ -74,12 +72,12 @@ readJsonField() {
|
|||||||
|
|
||||||
readGuestStatus() {
|
readGuestStatus() {
|
||||||
|
|
||||||
local result msg rc
|
local result msg
|
||||||
|
|
||||||
result=$(readJsonField '.status') || return 1
|
result=$(readJsonField '.status') || return 1
|
||||||
|
|
||||||
if [[ "$result" != "success" ]]; then
|
if [[ "$result" != "success" ]]; then
|
||||||
{ msg=$(jq -r '.message // empty' <<< "$json"); rc=$?; } || :
|
{ msg=$(jq -r '.message // empty' <<< "$json"); local rc=$?; } || :
|
||||||
|
|
||||||
if (( rc != 0 )); then
|
if (( rc != 0 )); then
|
||||||
error "$jq_err $rc ( $json )"
|
error "$jq_err $rc ( $json )"
|
||||||
@@ -140,14 +138,29 @@ pollGuestLocation() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkAddressConflict() {
|
||||||
|
|
||||||
|
local guest_ip="${location%:*}"
|
||||||
|
local container_ip=""
|
||||||
|
|
||||||
|
[ -s "$address" ] && container_ip=$(<"$address")
|
||||||
|
[ -z "$container_ip" ] && return 0
|
||||||
|
[[ "$guest_ip" != "$container_ip" ]] && return 0
|
||||||
|
|
||||||
|
warn "DSM is using the same IP as the container, this will cause connectivity issues."
|
||||||
|
warn "change the container's macvlan IP or assign DSM a different address in your router."
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
writeDhcpPage() {
|
writeDhcpPage() {
|
||||||
|
|
||||||
local title body script html
|
local html
|
||||||
|
|
||||||
msg="http://$location"
|
msg="http://$location"
|
||||||
title="<title>Virtual DSM</title>"
|
local title="<title>Virtual DSM</title>"
|
||||||
body="The location of DSM is <a href='http://$location'>http://$location</a>"
|
local body="The location of DSM is <a href='http://$location'>http://$location</a>"
|
||||||
script="<script>setTimeout(function(){ window.location.assign('http://$location'); }, 3000);</script>"
|
local script="<script>setTimeout(function(){ window.location.assign('http://$location'); }, 3000);</script>"
|
||||||
|
|
||||||
html=$(<"$template")
|
html=$(<"$template")
|
||||||
html="${html/\[1\]/$title}"
|
html="${html/\[1\]/$title}"
|
||||||
@@ -164,11 +177,11 @@ writeDhcpPage() {
|
|||||||
|
|
||||||
buildStaticMessage() {
|
buildStaticMessage() {
|
||||||
|
|
||||||
local nic ip port
|
local nic ip
|
||||||
|
|
||||||
nic=$(<"$driver")
|
nic=$(<"$driver")
|
||||||
ip=$(<"$address")
|
ip=$(<"$address")
|
||||||
port="${location##*:}"
|
local port="${location##*:}"
|
||||||
|
|
||||||
if [[ "${nic,,}" != "macvlan" ]]; then
|
if [[ "${nic,,}" != "macvlan" ]]; then
|
||||||
msg="port $port"
|
msg="port $port"
|
||||||
@@ -196,6 +209,7 @@ exitIfShuttingDown
|
|||||||
location=$(<"$file")
|
location=$(<"$file")
|
||||||
|
|
||||||
if enabled "$DHCP"; then
|
if enabled "$DHCP"; then
|
||||||
|
checkAddressConflict
|
||||||
writeDhcpPage
|
writeDhcpPage
|
||||||
else
|
else
|
||||||
buildStaticMessage
|
buildStaticMessage
|
||||||
|
|||||||
+82
-7
@@ -2,6 +2,7 @@
|
|||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
info="/run/shm/msg.html"
|
info="/run/shm/msg.html"
|
||||||
|
info_tmp="${info}.${BASHPID}.tmp"
|
||||||
|
|
||||||
escape() {
|
escape() {
|
||||||
|
|
||||||
@@ -17,6 +18,23 @@ escape() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writeInfo() {
|
||||||
|
|
||||||
|
local content="$1"
|
||||||
|
|
||||||
|
if ! printf '%s\n' "$content" > "$info_tmp"; then
|
||||||
|
rm -f -- "$info_tmp"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! mv -f -- "$info_tmp" "$info"; then
|
||||||
|
rm -f -- "$info_tmp"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
getBytes() {
|
getBytes() {
|
||||||
|
|
||||||
local path="$1"
|
local path="$1"
|
||||||
@@ -48,6 +66,24 @@ getBytes() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getStatus() {
|
||||||
|
|
||||||
|
local file="$1"
|
||||||
|
local bytes total extra=""
|
||||||
|
|
||||||
|
[ -r "$file" ] || return 1
|
||||||
|
read -r bytes total extra < "$file" || return 1
|
||||||
|
|
||||||
|
if [[ ! "$bytes" =~ ^[0-9]+$ ||
|
||||||
|
! "$total" =~ ^[0-9]+$ ||
|
||||||
|
-n "$extra" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%s %s\n' "$bytes" "$total"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
formatSize() {
|
formatSize() {
|
||||||
|
|
||||||
local bytes="$1"
|
local bytes="$1"
|
||||||
@@ -117,7 +153,19 @@ printSizeProgress() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
finishLogProgress() {
|
stopProgress() {
|
||||||
|
|
||||||
|
if [ -z "$status_file" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
stopping="Y"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
finishProgress() {
|
||||||
|
|
||||||
|
rm -f -- "$info_tmp"
|
||||||
|
|
||||||
if [[ "$output" == "log" && "$printed" == "Y" ]]; then
|
if [[ "$output" == "log" && "$printed" == "Y" ]]; then
|
||||||
printf '\n'
|
printf '\n'
|
||||||
@@ -132,6 +180,7 @@ body=$(escape "$3")
|
|||||||
output="${4:-}"
|
output="${4:-}"
|
||||||
step_bytes="${5:-536870912}"
|
step_bytes="${5:-536870912}"
|
||||||
mode="${6:-apparent}"
|
mode="${6:-apparent}"
|
||||||
|
status_file="${7:-}"
|
||||||
|
|
||||||
if [[ -n "$total" && ! "$total" =~ ^(0|[1-9][0-9]*)$ ]]; then
|
if [[ -n "$total" && ! "$total" =~ ^(0|[1-9][0-9]*)$ ]]; then
|
||||||
printf 'Invalid total size: %s\n' "$total" >&2
|
printf 'Invalid total size: %s\n' "$total" >&2
|
||||||
@@ -163,13 +212,15 @@ printed="N"
|
|||||||
next_percent=10
|
next_percent=10
|
||||||
next_bytes="$step_bytes"
|
next_bytes="$step_bytes"
|
||||||
log_mode="percent"
|
log_mode="percent"
|
||||||
|
stopping="N"
|
||||||
|
|
||||||
if [ -z "$total" ] || [[ "$total" == "0" ]]; then
|
if [ -z "$total" ] || [[ "$total" == "0" ]]; then
|
||||||
log_mode="size"
|
log_mode="size"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
trap finishLogProgress EXIT
|
trap finishProgress EXIT
|
||||||
trap 'exit 0' HUP INT QUIT TERM
|
trap 'exit 0' HUP INT QUIT
|
||||||
|
trap stopProgress TERM
|
||||||
|
|
||||||
if [[ "$body" == *"..." ]]; then
|
if [[ "$body" == *"..." ]]; then
|
||||||
body="<p class=\"loading\">${body::-3}</p>"
|
body="<p class=\"loading\">${body::-3}</p>"
|
||||||
@@ -177,13 +228,34 @@ fi
|
|||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
|
|
||||||
|
final_pass="${stopping:-}"
|
||||||
bytes=$(getBytes "$path" "$mode")
|
bytes=$(getBytes "$path" "$mode")
|
||||||
|
effective_total="$total"
|
||||||
|
|
||||||
|
if [ -n "$status_file" ] && status=$(getStatus "$status_file"); then
|
||||||
|
read -r status_bytes status_total <<< "$status"
|
||||||
|
bytes="$status_bytes"
|
||||||
|
|
||||||
|
if (( status_total > 0 )); then
|
||||||
|
effective_total="$status_total"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# A real total may become available shortly after aria2 starts.
|
||||||
|
if [[ "$log_mode" == "size" &&
|
||||||
|
"$printed" == "N" &&
|
||||||
|
-n "$effective_total" &&
|
||||||
|
"$effective_total" != "0" ]]; then
|
||||||
|
log_mode="percent"
|
||||||
|
fi
|
||||||
|
|
||||||
if (( bytes > 4096 )); then
|
if (( bytes > 4096 )); then
|
||||||
|
|
||||||
write_html="Y"
|
write_html="Y"
|
||||||
|
|
||||||
if [ -z "$total" ] || [[ "$total" == "0" ]] || (( bytes > total )); then
|
if [ -z "$effective_total" ] ||
|
||||||
|
[[ "$effective_total" == "0" ]] ||
|
||||||
|
(( bytes > effective_total )); then
|
||||||
size=$(formatSize "$bytes")
|
size=$(formatSize "$bytes")
|
||||||
|
|
||||||
if [[ "$output" == "log" ]]; then
|
if [[ "$output" == "log" ]]; then
|
||||||
@@ -197,7 +269,7 @@ while true; do
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# Truncate to one decimal so progress is never reported early.
|
# Truncate to one decimal so progress is never reported early.
|
||||||
progress=$((bytes * 1000 / total))
|
progress=$((bytes * 1000 / effective_total))
|
||||||
(( progress > 1000 )) && progress=1000
|
(( progress > 1000 )) && progress=1000
|
||||||
|
|
||||||
percent=$((progress / 10))
|
percent=$((progress / 10))
|
||||||
@@ -219,9 +291,12 @@ while true; do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$write_html" == "Y" ]]; then
|
if [[ "$write_html" == "Y" ]]; then
|
||||||
printf '%s\n' "${body//(\[P\])/($size)}" > "$info"
|
writeInfo "${body//(\[P\])/($size)}"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sleep 1 & wait $!
|
[[ "$final_pass" == "Y" ]] && break
|
||||||
|
|
||||||
|
sleep 1 &
|
||||||
|
wait $! || :
|
||||||
done
|
done
|
||||||
|
|||||||
+8
-15
@@ -41,7 +41,7 @@ detectEngine() {
|
|||||||
|
|
||||||
detectRootless() {
|
detectRootless() {
|
||||||
|
|
||||||
local uid_map=""
|
local uid_map
|
||||||
|
|
||||||
uid_map=$(awk '{$1=$1; print}' /proc/self/uid_map 2>/dev/null || true)
|
uid_map=$(awk '{$1=$1; print}' /proc/self/uid_map 2>/dev/null || true)
|
||||||
|
|
||||||
@@ -58,8 +58,6 @@ checkPrivileged() {
|
|||||||
|
|
||||||
local cap_bnd
|
local cap_bnd
|
||||||
local last_cap
|
local last_cap
|
||||||
local max_cap
|
|
||||||
|
|
||||||
# Get the capability bounding set
|
# Get the capability bounding set
|
||||||
cap_bnd=$(grep '^CapBnd:' /proc/$$/status | awk '{print $2}')
|
cap_bnd=$(grep '^CapBnd:' /proc/$$/status | awk '{print $2}')
|
||||||
cap_bnd=$(printf "%d" "0x${cap_bnd}")
|
cap_bnd=$(printf "%d" "0x${cap_bnd}")
|
||||||
@@ -68,7 +66,7 @@ checkPrivileged() {
|
|||||||
last_cap=$(cat /proc/sys/kernel/cap_last_cap)
|
last_cap=$(cat /proc/sys/kernel/cap_last_cap)
|
||||||
|
|
||||||
# Calculate the maximum capability value
|
# Calculate the maximum capability value
|
||||||
max_cap=$(((1 << (last_cap + 1)) - 1))
|
local max_cap=$(((1 << (last_cap + 1)) - 1))
|
||||||
|
|
||||||
if [ "$cap_bnd" -eq "$max_cap" ]; then
|
if [ "$cap_bnd" -eq "$max_cap" ]; then
|
||||||
PRIVILEGED="Y"
|
PRIVILEGED="Y"
|
||||||
@@ -144,9 +142,7 @@ finiteMemoryLimit() {
|
|||||||
|
|
||||||
local limit="$1"
|
local limit="$1"
|
||||||
local sentinel="4611686018427387904"
|
local sentinel="4611686018427387904"
|
||||||
local i=0
|
local i
|
||||||
local left=""
|
|
||||||
local right=""
|
|
||||||
|
|
||||||
[[ "$limit" =~ ^[0-9]+$ ]] || return 1
|
[[ "$limit" =~ ^[0-9]+$ ]] || return 1
|
||||||
|
|
||||||
@@ -154,8 +150,8 @@ finiteMemoryLimit() {
|
|||||||
(( ${#limit} > ${#sentinel} )) && return 1
|
(( ${#limit} > ${#sentinel} )) && return 1
|
||||||
|
|
||||||
for (( i=0; i<${#sentinel}; i++ )); do
|
for (( i=0; i<${#sentinel}; i++ )); do
|
||||||
left="${limit:i:1}"
|
local left="${limit:i:1}"
|
||||||
right="${sentinel:i:1}"
|
local right="${sentinel:i:1}"
|
||||||
|
|
||||||
(( left < right )) && return 0
|
(( left < right )) && return 0
|
||||||
(( left > right )) && return 1
|
(( left > right )) && return 1
|
||||||
@@ -166,11 +162,8 @@ finiteMemoryLimit() {
|
|||||||
|
|
||||||
getMemoryInfo() {
|
getMemoryInfo() {
|
||||||
|
|
||||||
local host_total=""
|
local limit="" current=""
|
||||||
local host_avail=""
|
local host_total host_avail
|
||||||
local limit=""
|
|
||||||
local current=""
|
|
||||||
local available=""
|
|
||||||
|
|
||||||
host_total=$(free -b | awk '/^Mem:/ {print $2; exit}')
|
host_total=$(free -b | awk '/^Mem:/ {print $2; exit}')
|
||||||
host_avail=$(free -b | awk '/^Mem:/ {print $7; exit}')
|
host_avail=$(free -b | awk '/^Mem:/ {print $7; exit}')
|
||||||
@@ -189,7 +182,7 @@ getMemoryInfo() {
|
|||||||
if finiteMemoryLimit "$limit" && [[ "$current" =~ ^[0-9]+$ ]]; then
|
if finiteMemoryLimit "$limit" && [[ "$current" =~ ^[0-9]+$ ]]; then
|
||||||
(( limit < RAM_TOTAL )) && RAM_TOTAL="$limit"
|
(( limit < RAM_TOTAL )) && RAM_TOTAL="$limit"
|
||||||
|
|
||||||
available=$(( limit - current ))
|
local available=$(( limit - current ))
|
||||||
(( available < 0 )) && available=0
|
(( available < 0 )) && available=0
|
||||||
(( available < RAM_AVAIL )) && RAM_AVAIL="$available"
|
(( available < RAM_AVAIL )) && RAM_AVAIL="$available"
|
||||||
fi
|
fi
|
||||||
|
|||||||
+68
-15
@@ -15,24 +15,35 @@ WSD_PID="$QEMU_DIR/websocketd.pid"
|
|||||||
prepareWebFiles() {
|
prepareWebFiles() {
|
||||||
|
|
||||||
cp -r /var/www/* "$QEMU_DIR" || return 1
|
cp -r /var/www/* "$QEMU_DIR" || return 1
|
||||||
rm -f "$WSD_PID" "$WEB_PID" "$WSD_LOG" || return 1
|
rm -f -- "$WSD_PID" "$WEB_PID" "$WSD_LOG" || return 1
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
configureWebPorts() {
|
configureWebPorts() {
|
||||||
|
|
||||||
sed -i "s/listen 5000 default_server;/listen $WEB_PORT default_server;/g" /etc/nginx/sites-enabled/web.conf
|
if ! sed -i \
|
||||||
sed -i "s/proxy_pass http:\/\/127.0.0.1:8004\/;/proxy_pass http:\/\/127.0.0.1:$WSD_PORT\/;/g" /etc/nginx/sites-enabled/web.conf
|
-e "s|listen 5000 default_server;|listen $WEB_PORT default_server;|g" \
|
||||||
|
-e "s|proxy_pass http://127.0.0.1:8004/;|proxy_pass http://127.0.0.1:$WSD_PORT/;|g" \
|
||||||
|
/etc/nginx/sites-enabled/web.conf; then
|
||||||
|
error "Failed to configure webserver ports!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
configureIpv6Listen() {
|
configureIpv6Listen() {
|
||||||
|
|
||||||
# shellcheck disable=SC2143
|
|
||||||
if [ -f /proc/net/if_inet6 ] && [[ "$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null)" != "1" ]]; then
|
if [ -f /proc/net/if_inet6 ] && [[ "$(cat /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null)" != "1" ]]; then
|
||||||
sed -i "s/listen $WEB_PORT default_server;/listen [::]:$WEB_PORT default_server ipv6only=off;/g" /etc/nginx/sites-enabled/web.conf
|
|
||||||
|
if ! sed -i \
|
||||||
|
"s/listen $WEB_PORT default_server;/listen [::]:$WEB_PORT default_server ipv6only=off;/g" \
|
||||||
|
/etc/nginx/sites-enabled/web.conf; then
|
||||||
|
error "Failed to configure IPv6 webserver listener!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
@@ -49,6 +60,22 @@ configureWebServer() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stopWebServer() {
|
||||||
|
|
||||||
|
local pid
|
||||||
|
|
||||||
|
if [ -s "$WEB_PID" ] && read -r pid < "$WEB_PID" && [ -n "$pid" ]; then
|
||||||
|
pKill "$pid" 2
|
||||||
|
|
||||||
|
if isAlive "$pid"; then
|
||||||
|
kill -9 -- "$pid" 2>/dev/null || :
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f -- "$WEB_PID"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
startWebServer() {
|
startWebServer() {
|
||||||
|
|
||||||
# Start webserver
|
# Start webserver
|
||||||
@@ -57,6 +84,22 @@ startWebServer() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stopWebsocketServer() {
|
||||||
|
|
||||||
|
local pid
|
||||||
|
|
||||||
|
if [ -s "$WSD_PID" ] && read -r pid < "$WSD_PID" && [ -n "$pid" ]; then
|
||||||
|
pKill "$pid" 2
|
||||||
|
|
||||||
|
if isAlive "$pid"; then
|
||||||
|
kill -9 -- "$pid" 2>/dev/null || :
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f -- "$WSD_PID"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
startWebsocketServer() {
|
startWebsocketServer() {
|
||||||
|
|
||||||
# Start websocket server
|
# Start websocket server
|
||||||
@@ -70,17 +113,23 @@ startWebsocketServer() {
|
|||||||
|
|
||||||
if ! echo "$pid" > "$WSD_PID"; then
|
if ! echo "$pid" > "$WSD_PID"; then
|
||||||
kill "$pid" 2>/dev/null || :
|
kill "$pid" 2>/dev/null || :
|
||||||
|
rm -f -- "$WSD_PID"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sleep 0.1
|
local i
|
||||||
|
for (( i = 1; i <= 5; i++ )); do
|
||||||
|
|
||||||
if ! isAlive "$pid"; then
|
if ! isAlive "$pid"; then
|
||||||
rm -f "$WSD_PID"
|
rm -f -- "$WSD_PID"
|
||||||
[ -s "$WSD_LOG" ] && cat "$WSD_LOG" >&2
|
[ -s "$WSD_LOG" ] && cat "$WSD_LOG" >&2
|
||||||
error "Failed to start websocket server!"
|
error "Failed to start websocket server!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
sleep 0.1
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -93,7 +142,11 @@ disabled "${WEB:-}" && return 0
|
|||||||
|
|
||||||
configureWebServer
|
configureWebServer
|
||||||
|
|
||||||
startWebServer
|
if startWebServer && startWebsocketServer; then
|
||||||
startWebsocketServer
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
return 0
|
stopWebsocketServer || :
|
||||||
|
stopWebServer || :
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|||||||
+17
-4
@@ -3,6 +3,8 @@ set -Eeuo pipefail
|
|||||||
|
|
||||||
lastmsg=""
|
lastmsg=""
|
||||||
path="/run/shm/msg.html"
|
path="/run/shm/msg.html"
|
||||||
|
dir=$(dirname -- "$path")
|
||||||
|
name=$(basename -- "$path")
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
|
|
||||||
@@ -17,15 +19,26 @@ refresh() {
|
|||||||
|
|
||||||
lastmsg="$msg"
|
lastmsg="$msg"
|
||||||
echo "s: $msg"
|
echo "s: $msg"
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh
|
refresh
|
||||||
|
|
||||||
inotifywait -m "$path" |
|
inotifywait \
|
||||||
while read -r fp event fn; do
|
-m -q \
|
||||||
|
-e close_write,moved_to,delete \
|
||||||
|
--format '%e %f' \
|
||||||
|
"$dir" |
|
||||||
|
while read -r event file; do
|
||||||
|
|
||||||
|
[[ "$file" == "$name" ]] || continue
|
||||||
|
|
||||||
case "${event,,}" in
|
case "${event,,}" in
|
||||||
"modify"* ) refresh ;;
|
"delete"* )
|
||||||
"delete_self" ) echo "c: vnc" ;;
|
echo "c: vnc" ;;
|
||||||
|
"close_write"* | "moved_to"* )
|
||||||
|
refresh ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|||||||
+27
-12
@@ -133,8 +133,7 @@ waitPid() {
|
|||||||
|
|
||||||
waitPidFile() {
|
waitPidFile() {
|
||||||
|
|
||||||
local i=0
|
local i=0 pid
|
||||||
local pid=""
|
|
||||||
local file="$1"
|
local file="$1"
|
||||||
local timeout="${2:-10}"
|
local timeout="${2:-10}"
|
||||||
|
|
||||||
@@ -201,7 +200,7 @@ fKill() {
|
|||||||
|
|
||||||
sKill() {
|
sKill() {
|
||||||
|
|
||||||
local pid=""
|
local pid
|
||||||
local file="$1"
|
local file="$1"
|
||||||
|
|
||||||
[ ! -s "$file" ] && return 0
|
[ ! -s "$file" ] && return 0
|
||||||
@@ -300,6 +299,25 @@ writeFile() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writeAtomic() {
|
||||||
|
|
||||||
|
local path="$1"
|
||||||
|
local content="$2"
|
||||||
|
local tmp="${path}.${BASHPID}.tmp"
|
||||||
|
|
||||||
|
if ! printf '%s\n' "$content" > "$tmp"; then
|
||||||
|
rm -f -- "$tmp"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! mv -f -- "$tmp" "$path"; then
|
||||||
|
rm -f -- "$tmp"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
readFile() {
|
readFile() {
|
||||||
|
|
||||||
local path="$1"
|
local path="$1"
|
||||||
@@ -362,8 +380,7 @@ restoreState() {
|
|||||||
|
|
||||||
escape () {
|
escape () {
|
||||||
|
|
||||||
local s
|
local s=${1//&/\&}
|
||||||
s=${1//&/\&}
|
|
||||||
s=${s//</\<}
|
s=${s//</\<}
|
||||||
s=${s//>/\>}
|
s=${s//>/\>}
|
||||||
s=${s//'"'/\"}
|
s=${s//'"'/\"}
|
||||||
@@ -389,7 +406,7 @@ html() {
|
|||||||
|
|
||||||
local title
|
local title
|
||||||
local body
|
local body
|
||||||
local script
|
local script="${2:-}"
|
||||||
local footer
|
local footer
|
||||||
|
|
||||||
title=$(escape "$APP")
|
title=$(escape "$APP")
|
||||||
@@ -401,8 +418,6 @@ html() {
|
|||||||
body="<p class=\"loading\">${body/.../}</p>"
|
body="<p class=\"loading\">${body/.../}</p>"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[ -n "${2:-}" ] && script="$2" || script=""
|
|
||||||
|
|
||||||
local HTML
|
local HTML
|
||||||
HTML=$(<"$TEMPLATE")
|
HTML=$(<"$TEMPLATE")
|
||||||
HTML="${HTML/\[1\]/$title}"
|
HTML="${HTML/\[1\]/$title}"
|
||||||
@@ -411,8 +426,8 @@ html() {
|
|||||||
HTML="${HTML/\[4\]/$footer}"
|
HTML="${HTML/\[4\]/$footer}"
|
||||||
HTML="${HTML/\[5\]/$FOOTER2}"
|
HTML="${HTML/\[5\]/$FOOTER2}"
|
||||||
|
|
||||||
echo "$HTML" > "$PAGE" || return 1
|
writeAtomic "$PAGE" "$HTML" || return 1
|
||||||
echo "$body" > "$INFO" || return 1
|
writeAtomic "$INFO" "$body" || return 1
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -459,9 +474,9 @@ getCountry() {
|
|||||||
|
|
||||||
local url=$1
|
local url=$1
|
||||||
local query=$2
|
local query=$2
|
||||||
local rc json result
|
local json result
|
||||||
|
|
||||||
{ json=$(curl -m 5 -H "Accept: application/json" -sfk "$url"); rc=$?; } || :
|
{ json=$(curl -m 5 -H "Accept: application/json" -sfk "$url"); local rc=$?; } || :
|
||||||
(( rc != 0 )) && return 0
|
(( rc != 0 )) && return 0
|
||||||
|
|
||||||
{ result=$(echo "$json" | jq -r "$query" 2> /dev/null); rc=$?; } || :
|
{ result=$(echo "$json" | jq -r "$query" 2> /dev/null); rc=$?; } || :
|
||||||
|
|||||||
+41
-8
@@ -1,15 +1,27 @@
|
|||||||
|
var timer;
|
||||||
var request;
|
var request;
|
||||||
var booting = false;
|
var booting = false;
|
||||||
var interval = 1000;
|
var interval = 1000;
|
||||||
|
|
||||||
|
function abortRequest() {
|
||||||
|
|
||||||
|
if (!request) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.onreadystatechange = null;
|
||||||
|
request.abort();
|
||||||
|
request = null;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function getInfo() {
|
function getInfo() {
|
||||||
|
|
||||||
var url = "msg.html";
|
var url = "msg.html";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (request) {
|
abortRequest();
|
||||||
request.abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.XMLHttpRequest) {
|
if (window.XMLHttpRequest) {
|
||||||
request = new XMLHttpRequest();
|
request = new XMLHttpRequest();
|
||||||
@@ -56,7 +68,10 @@ function processInfo() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg = request.responseText;
|
var response = request;
|
||||||
|
request = null;
|
||||||
|
|
||||||
|
var msg = response.responseText;
|
||||||
if (msg == null || msg.length == 0) {
|
if (msg == null || msg.length == 0) {
|
||||||
|
|
||||||
if (booting) {
|
if (booting) {
|
||||||
@@ -68,9 +83,9 @@ function processInfo() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var notFound = (request.status == 404);
|
var notFound = (response.status == 404);
|
||||||
|
|
||||||
if (request.status == 200) {
|
if (response.status == 200) {
|
||||||
if (msg.toLowerCase().indexOf("<html>") !== -1) {
|
if (msg.toLowerCase().indexOf("<html>") !== -1) {
|
||||||
notFound = true;
|
notFound = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -88,7 +103,7 @@ function processInfo() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
setError("Error: Received statuscode " + request.status);
|
setError("Error: Received statuscode " + response.status);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -157,7 +172,9 @@ function setError(text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function schedule() {
|
function schedule() {
|
||||||
setTimeout(getInfo, interval);
|
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = setTimeout(getInfo, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
function reload() {
|
function reload() {
|
||||||
@@ -179,11 +196,27 @@ function connect() {
|
|||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case "s":
|
case "s":
|
||||||
|
|
||||||
|
var aborted = abortRequest();
|
||||||
|
|
||||||
processMsg(msg);
|
processMsg(msg);
|
||||||
|
|
||||||
|
if (aborted &&
|
||||||
|
msg.toLowerCase().indexOf("href=") == -1) {
|
||||||
|
schedule();
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "e":
|
case "e":
|
||||||
|
|
||||||
|
if (abortRequest()) {
|
||||||
|
schedule();
|
||||||
|
}
|
||||||
|
|
||||||
setError(msg);
|
setError(msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.warn("Unknown event: " + cmd);
|
console.warn("Unknown event: " + cmd);
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user