Compare commits

...
9 Commits
9 changed files with 333 additions and 167 deletions
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+18 -2
View File
@@ -153,6 +153,16 @@ printSizeProgress() {
return 0 return 0
} }
stopProgress() {
if [ -z "$status_file" ]; then
exit 0
fi
stopping="Y"
return 0
}
finishProgress() { finishProgress() {
rm -f -- "$info_tmp" rm -f -- "$info_tmp"
@@ -202,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 finishProgress 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>"
@@ -216,6 +228,7 @@ fi
while true; do while true; do
final_pass="${stopping:-}"
bytes=$(getBytes "$path" "$mode") bytes=$(getBytes "$path" "$mode")
effective_total="$total" effective_total="$total"
@@ -282,5 +295,8 @@ while true; do
fi fi
fi fi
sleep 1 & wait $! [[ "$final_pass" == "Y" ]] && break
sleep 1 &
wait $! || :
done done
+8 -15
View File
@@ -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
+53 -11
View File
@@ -15,7 +15,7 @@ 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
} }
@@ -60,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
@@ -68,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
@@ -81,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
} }
@@ -104,7 +142,11 @@ disabled "${WEB:-}" && return 0
configureWebServer configureWebServer
startWebServer if startWebServer && startWebsocketServer; then
startWebsocketServer return 0
fi
return 0 stopWebsocketServer || :
stopWebServer || :
return 1
+6 -10
View File
@@ -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
@@ -381,8 +380,7 @@ restoreState() {
escape () { escape () {
local s local s=${1//&/\&amp;}
s=${1//&/\&amp;}
s=${s//</\&lt;} s=${s//</\&lt;}
s=${s//>/\&gt;} s=${s//>/\&gt;}
s=${s//'"'/\&quot;} s=${s//'"'/\&quot;}
@@ -408,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")
@@ -420,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}"
@@ -478,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=$?; } || :