diff --git a/.build/images/dietpi-installer b/.build/images/dietpi-installer
index fa8757ec49..f1f0d781fc 100755
--- a/.build/images/dietpi-installer
+++ b/.build/images/dietpi-installer
@@ -637,7 +637,13 @@ _EOF_
local armbian_packages=0
if (( $G_HW_MODEL < 10 ))
then
- G_EXEC mv "$dir/.build/images/RPi/config.txt" /boot/firmware/
+ # Temporary workaround for misplaced dtoverlay=vc4-kms-v3d above dtparam's: https://forums.raspberrypi.com/viewtopic.php?p=2385679#p2385532
+ if [[ $G_GITOWNER/$G_GITBRANCH == 'MichaIng/master' ]]
+ then
+ G_EXEC curl -sSfo /boot/firmware/config.txt 'https://raw.githubusercontent.com/MichaIng/DietPi/dev/.build/images/RPi/config.txt'
+ else
+ G_EXEC mv "$dir/.build/images/RPi/config.txt" /boot/firmware/
+ fi
G_EXEC eval "echo 'root=PARTUUID=$(findmnt -Ufnro PARTUUID /) rootfstype=$(findmnt -Ufnro FSTYPE /) rootwait fsck.repair=yes net.ifnames=0 logo.nologo console=serial0,115200 console=tty1' > /boot/firmware/cmdline.txt"
# Boot in 64-bit mode if this is a 64-bit image
[[ $userland_arch == 'arm64' ]] && G_CONFIG_INJECT 'arm_64bit=' 'arm_64bit=1' /boot/firmware/config.txt
@@ -744,18 +750,19 @@ setenv bootlabel "DietPi"' /boot/boot.cmd
# Overlay prefix
case $G_HW_MODEL in
14) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rockchip-rk3588-odroidm2 rockchip-rk3588' /boot/dietpiEnv.txt;;
- 73) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rk3308' /boot/dietpiEnv.txt;;
77) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rockchip-rk3568-rock-3a rockchip-rk3568-hk rockchip-rk3566' /boot/dietpiEnv.txt;;
78) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rock-5b rock-5 rockchip-rk3588 rk3588' /boot/dietpiEnv.txt;;
80|106) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=orangepi-5 rockchip-rk3588 rk3588' /boot/dietpiEnv.txt;;
82) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=orangepi-5-plus rockchip-rk3588 rk3588' /boot/dietpiEnv.txt;;
85) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rock-5a rock-5 rockchip-rk3588 rk3588' /boot/dietpiEnv.txt;;
- 90) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rockchip-rk3566 rockchip-rk3568 radxa-zero3 rk3568' /boot/dietpiEnv.txt;;
+ 90) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rk35xx-radxa-zero-3w rockchip-rk3566 rockchip-rk3568 radxa-zero3 rk3568' /boot/dietpiEnv.txt;;
92) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=nanopi-m6 rockchip-rk3588-nanopi-m6 rockchip-rk3588 rk3588' /boot/dietpiEnv.txt;;
93) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=orangepi-5-pro rockchip-rk3588 rk3588' /boot/dietpiEnv.txt;;
94) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=orangepi-5-ultra rockchip-rk3588 rk3588' /boot/dietpiEnv.txt;;
95) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=orangepi-cm5 rockchip-rk3588 rk3588' /boot/dietpiEnv.txt;;
+ 73) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rk3308' /boot/dietpiEnv.txt;; # RK3308 mainline
43|55|56) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rockchip-rk3328' /boot/dietpiEnv.txt;; # RK3328 mainline
+ 42|46|47|48|68|72|86|105) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rockchip-rk3399' /boot/dietpiEnv.txt;; # RK3399 mainline
79|91) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rockchip-rk3588 rk3588' /boot/dietpiEnv.txt;; # RK3588 mainline + vendor
19|87|100|101) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rockchip-rk3566 rockchip-rk3568-hk' /boot/dietpiEnv.txt;; # RK3566 mainline
18|76) G_CONFIG_INJECT 'overlay_prefix=' 'overlay_prefix=rockchip-rk3568-hk rockchip-rk3566' /boot/dietpiEnv.txt;; # RK3568 mainline
@@ -765,7 +772,8 @@ setenv bootlabel "DietPi"' /boot/boot.cmd
esac
# Overlays
case $G_HW_MODEL in
- 80|91|94|106) G_CONFIG_INJECT 'overlays=' 'overlays=dwc3-host' /boot/dietpiEnv.txt;; # Switch USB-C and vertical USB 2.0 (shares controller with USB-C) to host mode by default
+ 91|94) G_CONFIG_INJECT 'overlays=' 'overlays=dwc3-host' /boot/dietpiEnv.txt;; # vendor: Switch USB-C and vertical USB 2.0 (shares controller with USB-C) to host mode by default
+ 80|106) G_CONFIG_INJECT 'overlays=' 'overlays=usb-c-host' /boot/dietpiEnv.txt;; # mainline: Switch USB-C and vertical USB 2.0 (shares controller with USB-C) to host mode by default
92) G_CONFIG_INJECT 'overlays=' 'overlays=display-dsi1-yx35' /boot/dietpiEnv.txt;; # Enable builtin LCD of official case
*) :;;
esac
@@ -957,8 +965,9 @@ setenv bootlabel "DietPi"' /boot/boot.cmd
# Block packages from RPi desktop which conflict with a native LXDE desktop:
# - https://github.com/MichaIng/DietPi/issues/1558#issuecomment-691206284
# - https://github.com/MichaIng/DietPi/issues/4687
+ # and cups-filters: https://github.com/MichaIng/DietPi/issues/8245
G_EXEC eval 'cat << '\''_EOF_'\'' > /etc/apt/preferences.d/dietpi-raspberrypi
-Package: src:openbox src:obconf src:pcmanfm src:libfm src:gtk* src:lx*
+Package: src:cups-filters src:openbox src:obconf src:pcmanfm src:libfm src:gtk* src:lx*
Pin: origin archive.raspberrypi.com
Pin-Priority: -1
_EOF_'
@@ -1947,29 +1956,10 @@ _EOF_'
G_EXEC_DESC='Configuring network interfaces'
G_EXEC eval 'cat << _EOF_ > /etc/network/interfaces
# Location: /etc/network/interfaces
-# Please modify network settings via: dietpi-config
-# Or create your own drop-ins in: /etc/network/interfaces.d/
+# Network settings can be changed via dietpi-network.
# Drop-in configs
source interfaces.d/*
-
-# Ethernet
-#allow-hotplug eth0
-iface eth0 inet dhcp
-address 192.168.0.100
-netmask 255.255.255.0
-gateway 192.168.0.1
-#dns-nameservers 9.9.9.9 149.112.112.112
-
-# WiFi
-#allow-hotplug wlan0
-iface wlan0 inet dhcp
-address 192.168.0.100
-netmask 255.255.255.0
-gateway 192.168.0.1
-#dns-nameservers 9.9.9.9 149.112.112.112
-wireless-power off
-wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
_EOF_'
# Wait for network at boot by default
/boot/dietpi/func/dietpi-set_software boot_wait_for_network 1
diff --git a/.build/software/dietpi-software-build.bash b/.build/software/dietpi-software-build.bash
index 5d19d92d0a..e222db4fc2 100644
--- a/.build/software/dietpi-software-build.bash
+++ b/.build/software/dietpi-software-build.bash
@@ -19,7 +19,7 @@ else
'12.'*|'bookworm/sid') G_DISTRO=7;;
'13.'*|'trixie/sid') G_DISTRO=8;;
'14.'*|'forky/sid') G_DISTRO=9;;
- *) Error_Exit "Unsupported distro version \"$debian_version\"";;
+ *) Error_Exit "Unsupported Debian version \"$debian_version\"";;
esac
# Ubuntu ships with /etc/debian_version from Debian testing, hence we assume one version lower.
grep -q '^ID=ubuntu' /etc/os-release && ((G_DISTRO--))
@@ -101,7 +101,15 @@ apackages=('xz-utils' 'parted' 'fdisk' 'systemd-container')
emulation=0
(( $G_HW_ARCH == $arch || ( $G_HW_ARCH < 10 && $G_HW_ARCH > $arch ) )) || emulation=1
-(( $emulation )) && apackages+=('qemu-user-static')
+if (( $emulation ))
+then
+ if (( $G_DISTRO > 7 ))
+ then
+ apackages+=('qemu-user-binfmt')
+ else
+ apackages+=('qemu-user-static')
+ fi
+fi
G_AG_CHECK_INSTALL_PREREQ "${apackages[@]}"
diff --git a/.github/workflows/armbian.yml b/.github/workflows/armbian.yml
index 3d37590710..9d9b0ade41 100644
--- a/.github/workflows/armbian.yml
+++ b/.github/workflows/armbian.yml
@@ -196,6 +196,7 @@ jobs:
'rockchip64') BOARD='nanopi-m6';;
'sunxi') BOARD='nanopim1';;
'sunxi64') BOARD='orangepizero3';;
+ 'sun60iw2') BOARD='orangepizero3w';;
esac
echo "BOARD=$BOARD" >> "$GITHUB_ENV"
echo "BRANCH=$BRANCH" >> "$GITHUB_ENV"
diff --git a/.github/workflows/dietpi-software-build.yml b/.github/workflows/dietpi-software-build.yml
index 7ab4f61d2d..9a3897c3cf 100644
--- a/.github/workflows/dietpi-software-build.yml
+++ b/.github/workflows/dietpi-software-build.yml
@@ -30,7 +30,7 @@ jobs:
name: ${{ steps.name.outputs.name }}
arch: ${{ steps.arch.outputs.arch }}
dist: ${{ steps.dist.outputs.dist }}
- runs-on: ubuntu-24.04
+ runs-on: ubuntu-26.04
steps:
- id: name
run: |
@@ -72,18 +72,12 @@ jobs:
- { arch: armv7l, name: gzdoom }
fail-fast: false
name: "${{ matrix.name }} - ${{ matrix.arch }} - ${{ matrix.dist }}"
- runs-on: ${{ matrix.arch == 'x86_64' && 'ubuntu-24.04' || 'ubuntu-24.04-arm' }}
+ runs-on: ${{ matrix.arch == 'x86_64' && 'ubuntu-26.04' || 'ubuntu-26.04-arm' }}
steps:
- name: Build
run: sudo bash -c "G_GITOWNER=$GITHUB_REPOSITORY_OWNER G_GITBRANCH=$GITHUB_REF_NAME GH_TOKEN='${{ github.token }}'; $(curl -sSf "https://raw.githubusercontent.com/$GITHUB_REPOSITORY_OWNER/DietPi/$GITHUB_REF_NAME/.build/software/dietpi-software-build.bash")" -- -n '${{ matrix.name }}' -a '${{ matrix.arch }}' -d '${{ matrix.dist }}'
- name: Upload
run: |
- # SSH server and client keys
- mkdir ~/.ssh
- umask 377
- echo '${{ secrets.KNOWN_HOSTS }}' > ~/.ssh/known_hosts
- echo '${{ secrets.SSH_KEY }}' > ~/.ssh/id_ed25519
-
# Generate file lists
files=
urls='"https://dietpi.com/downloads/binaries/${{ matrix.dist }}/testing/"'
@@ -94,8 +88,15 @@ jobs:
urls="$urls,\"https://dietpi.com/downloads/binaries/${{ matrix.dist }}/testing/$i\""
done
files=${files#,}
- echo "Uploading file(s) $files to URL(s) $urls ..."
+ echo "Uploading file(s) $files to URL(s) $urls"
# Upload
+ trap 'rm -Rf ~/.ssh' EXIT
+ mkdir ~/.ssh
+ umask 377
+ echo '${{ secrets.KNOWN_HOSTS }}' > ~/.ssh/known_hosts
+ echo '${{ secrets.SSH_KEY }}' > ~/.ssh/id_ed25519
curl -T "{$files}" --key ~/.ssh/id_ed25519 '${{ secrets.UPLOAD_URL }}${{ matrix.dist }}/'
+ rm -R ~/.ssh
+
curl 'https://api.cloudflare.com/client/v4/zones/${{ secrets.CF_ZONE }}/purge_cache' -H 'Authorization: Bearer ${{ secrets.CF_TOKEN }}' -H 'Content-Type: application/json' --data "{\"files\":[$urls]}"
diff --git a/.github/workflows/quartz64.yml b/.github/workflows/quartz64.yml
index 96f7dcefdf..7b73e4cbc3 100644
--- a/.github/workflows/quartz64.yml
+++ b/.github/workflows/quartz64.yml
@@ -6,7 +6,7 @@ concurrency:
permissions: {}
jobs:
build:
- runs-on: ubuntu-24.04-arm
+ runs-on: ubuntu-26.04-arm
steps:
- uses: actions/setup-python@v7
with:
@@ -14,7 +14,7 @@ jobs:
check-latest: true
- name: Build init
run: |
- { python3 -m pip install --no-cache-dir -U pip setuptools wheel; python3 -m pip install --no-cache-dir -U pyelftools; } &
+ { python3 -m pip install --no-cache-dir -U pip setuptools; python3 -m pip install --no-cache-dir -U pyelftools; } &
{ sudo apt-get -q update; sudo DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -qq install make gcc libc6-dev flex bison bc libssl-dev swig libgnutls28-dev; } &
{ curl -fO 'https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/snapshot/linux-rolling-stable.tar.gz'; tar xf linux-rolling-stable.tar.gz; rm linux-rolling-stable.tar.gz; } &
uboot_version=$(curl -sSf 'https://api.github.com/repos/u-boot/u-boot/tags' | grep -Po '"name": *"\Kv[0-9.]*(?=")' | head -1)
@@ -171,10 +171,12 @@ jobs:
sudo rm -R firmware-quartz64a firmware-quartz64b firmware-soquartz
- name: Upload
run: |
- [ -d ~/.ssh ] || mkdir ~/.ssh
+ trap 'rm -Rf ~/.ssh' EXIT
+ mkdir ~/.ssh
umask 377
echo '${{ secrets.KNOWN_HOSTS }}' > ~/.ssh/known_hosts
echo '${{ secrets.SSH_KEY }}' > ~/.ssh/id_ed25519
curl -T 'firmware-{quartz64a,quartz64b,soquartz}.deb' --key ~/.ssh/id_ed25519 '${{ secrets.UPLOAD_URL }}all/'
+ rm -R ~/.ssh
curl 'https://api.cloudflare.com/client/v4/zones/${{ secrets.CF_ZONE }}/purge_cache' -H 'Authorization: Bearer ${{ secrets.CF_TOKEN }}' -H 'Content-Type: application/json' \
--data '{"files":["https://dietpi.com/downloads/binaries/testing/","https://dietpi.com/downloads/binaries/testing/firmware-quartz64a.deb","https://dietpi.com/downloads/binaries/testing/firmware-quartz64b.deb","https://dietpi.com/downloads/binaries/testing/firmware-soquartz.deb"]}'
diff --git a/.github/workflows/update_urls.bash b/.github/workflows/update_urls.bash
index 083df32d81..afb7415319 100644
--- a/.github/workflows/update_urls.bash
+++ b/.github/workflows/update_urls.bash
@@ -63,7 +63,7 @@ aREPLACE[$software_id]='version='\''$release'\''\;'
# Ampache
software_id=40
-aCHECK[$software_id]='curl -sSf '\''https://api.github.com/repos/ampache/ampache/releases/latest'\'' | grep -Po "\"browser_download_url\": *\"\K[^\"]*\/ampache-[0-9\.]*_all_php8.2\.zip(?=\")"'
+aCHECK[$software_id]='curl -sSf '\''https://api.github.com/repos/ampache/ampache/releases'\'' | grep -Po "\"browser_download_url\": *\"\K[^\"]*\/ampache-[0-9\.]*_all_php8.2\.zip(?=\")" | head -1'
aREGEX[$software_id]='https://github.com/ampache/ampache/releases/download/.*/ampache-.*_all_php\$PHP_VERSION.zip'
aREPLACE[$software_id]='${release/8.2/\$PHP_VERSION}'
@@ -424,6 +424,7 @@ aREGEX[$software_id]='https://github\.com/prometheus/prometheus/releases/downloa
for i in "${!aCHECK[@]}"
do
echo '------------------------------------------'
+ echo "Checking software ID $i ..."
# Fetch response once for entries with aARCH, to avoid redundant curl calls per architecture
# set -e ensures the script exits on any curl failure
response=
@@ -440,7 +441,6 @@ do
# Add GitHub token if set: only relevant for entries without aURL, since those still use curl in aCHECK
[[ $GH_TOKEN ]] && aCHECK[i]=${aCHECK[i]//curl -sSf \'https:\/\/api.github.com/curl -H \'Authorization: token $GH_TOKEN\' -sSf \'https://api.github.com}
- echo "Checking software ID $i ..."
# Loop through architectures
for arch in ${aARCH[i]:-dummy}
do
diff --git a/.meta/dietpi-bookworm-upgrade b/.meta/dietpi-bookworm-upgrade
index 36ea0841bb..f0134c96ee 100755
--- a/.meta/dietpi-bookworm-upgrade
+++ b/.meta/dietpi-bookworm-upgrade
@@ -133,7 +133,11 @@ then
fi
# Migrate OpenSSH server setting: https://manpages.debian.org/bookworm/sshd_config#KbdInteractiveAuthentication~2
-[[ -f '/etc/ssh/sshd_config' ]] && grep -q '^[[:blank:]]*ChallengeResponseAuthentication[[:blank:]]' /etc/ssh/sshd_config && ! grep -q '^[[:blank:]]*KbdInteractiveAuthentication[[:blank:]]' /etc/ssh/sshd_config && G_EXEC sed --follow-symlinks -Ei 's/^([[:blank:]]*)ChallengeResponseAuthentication([[:blank:]])/\1KbdInteractiveAuthentication\2/' /etc/ssh/sshd_config
+if [[ -f '/etc/ssh/sshd_config' ]]
+then
+ G_DIETPI-NOTIFY 2 'Updating deprecated OpenSSH setting: ChallengeResponseAuthentication => KbdInteractiveAuthentication'
+ G_EXEC sed --follow-symlinks -i 's/ChallengeResponseAuthentication/KbdInteractiveAuthentication/' /etc/ssh/sshd_config
+fi
# Remove deprecated OpenVPN setting: https://manpages.debian.org/bullseye/openvpn#keysize
for i in /etc/openvpn/*.{conf,ovpn}
diff --git a/.meta/dietpi-survey_report b/.meta/dietpi-survey_report
index 3c55df0c47..0d8d004d1b 100755
--- a/.meta/dietpi-survey_report
+++ b/.meta/dietpi-survey_report
@@ -628,15 +628,17 @@ shopt -s extglob # +(expr) syntax
aSOFTWARE_NAME10_4=()
aSOFTWARE_NAME10_5=()
aSOFTWARE_NAME10_6=()
+ aSOFTWARE_NAME10_7=()
for i in "${!aSOFTWARE_NAME10_3[@]}"
do
aSOFTWARE_NAME10_4[i]=${aSOFTWARE_NAME10_3[i]}
aSOFTWARE_NAME10_5[i]=${aSOFTWARE_NAME10_4[i]}
aSOFTWARE_NAME10_6[i]=${aSOFTWARE_NAME10_5[i]}
+ aSOFTWARE_NAME10_7[i]=${aSOFTWARE_NAME10_6[i]}
done
# Pre-create software counter array so that we can see also software (available in newest version) with 0 installs
- for i in "${aSOFTWARE_NAME10_6[@]}"
+ for i in "${aSOFTWARE_NAME10_7[@]}"
do
aSOFTWARE[$i]=0
done
@@ -1116,7 +1118,7 @@ shopt -s extglob # +(expr) syntax
DietPi-Survey statistics
- Below data is based on DietPi systems which have shown activity between $(date -u -d "@$(( $DATE_NOW - 15724800 ))" '+%Y-%m-%d') and $(date -u -d "@$DATE_NOW" '+%Y-%m-%d %T %Z'), i.e. either did a dietpi-update or a dietpi-software installation.
+ Below data is based on DietPi systems which have shown activity between $(date -u -d "@$(( $DATE_NOW - 15724800 ))" '+%F') and $(date -u -d "@$DATE_NOW" '+%F %T %Z'), i.e. either did a dietpi-update or a dietpi-software installation.
| Total system count | $SURVEY_COUNT_TOTAL |
| Systems sending survey data | $SURVEY_COUNT_OPTIN | $(( $SURVEY_COUNT_OPTIN * 100 / $SURVEY_COUNT_TOTAL ))% |
diff --git a/.meta/dietpi-trixie-upgrade b/.meta/dietpi-trixie-upgrade
index 69f4b2f0e3..3220051302 100644
--- a/.meta/dietpi-trixie-upgrade
+++ b/.meta/dietpi-trixie-upgrade
@@ -160,6 +160,13 @@ then
G_AGUG_ARGS=('-f')
fi
+if [[ $(dpkg-query -Wf '${Version}' kodi 2> /dev/null) == '3:20.'*'~bookworm' ]]
+then
+ G_DIETPI-NOTIFY 2 'Purging conflicting Kodi package from Raspberry Pi APT repository. It will be reinstalled along with the upgrade.'
+ G_EXEC_OUTPUT=1 G_EXEC dpkg -P kodi
+ G_AGDUG_ARGS+=('kodi')
+fi
+
G_DIETPI-NOTIFY 2 'Applying the actual upgrade to Debian Trixie'
/boot/dietpi/dietpi-services stop
G_AGUP
diff --git a/.update/patches b/.update/patches
index 7b67fdc53b..4e6b3eeb5e 100755
--- a/.update/patches
+++ b/.update/patches
@@ -1562,17 +1562,6 @@ _EOF_
G_EXEC eval 'echo -e '\''blacklist bcm2835_codec\nblacklist rpi_hevc_dec'\'' > /etc/modprobe.d/dietpi-disable_rpi_codec.conf'
G_EXEC sed --follow-symlinks -i '/^blacklist bcm2835_codec$/d' /etc/modprobe.d/dietpi-disable_rpi_camera.conf
fi
-
- # Software updates, migrations and patches
- if [[ -f '/boot/dietpi/.installed' ]]
- then
- # Chromium: https://dietpi.com/forum/t/22518
- if [[ -f '/etc/chromium.d/dietpi' ]] && grep -q ' --use-gl=egl"' /etc/chromium.d/dietpi
- then
- G_DIETPI-NOTIFY 2 'Fixing Chromium hardware acceleration'
- G_EXEC sed --follow-symlinks -i 's/ --use-gl=egl"/"/' /etc/chromium.d/dietpi
- fi
- fi
}
Patch_9_15()
@@ -2580,7 +2569,34 @@ Patch_10_6()
G_DIETPI-NOTIFY 2 'Applying stricter mode to vaultwarden.env, as it can be used to provide secret hashes like ADMIN_TOKEN. Use the "vaultwarden" group if any other user requires read access.'
G_EXEC chmod 'o-r' /mnt/dietpi_userdata/vaultwarden/vaultwarden.env
fi
+ fi
+}
+Patch_10_7()
+{
+ if [[ -f '/etc/chromium.d/dietpi' ]]
+ then
+ G_DIETPI-NOTIFY 2 'Removing obsolete Chromium flags, and apply "--no-sandbox" for calls as root user only'
+ # --no-sandbox allows root to run Chromium, and --test-type mutes a warning that --no-sandbox was used.
+ # shellcheck disable=SC2016
+ G_EXEC eval 'echo '\''[ "$(id -u)" -eq 0 ] && export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --no-sandbox --test-type"'\'' > /etc/chromium.d/dietpi'
+ fi
+
+ if [[ -f '/boot/firmware/config.txt' ]]
+ then
+ G_DIETPI-NOTIFY 2 'Moving all dtoverlay= lines to the end of config.txt, to assure dtparam= lines are effective.'
+ G_DIETPI-NOTIFY 2 'For reference: https://forums.raspberrypi.com/viewtopic.php?p=2385679#p2385532'
+ # shellcheck disable=SC2016
+ G_EXEC eval 'mawk '\''/^[[:blank:]#]*dtoverlay=/ { a = a $0 ORS; next } { print } END { printf "%s", a }'\'' /boot/firmware/config.txt > config.txt.new'
+ G_EXEC mv config.txt.new /boot/firmware/config.txt
+ fi
+
+ G_DIETPI-NOTIFY 2 'Removing obsolete dietpi.txt entry'
+ G_EXEC sed --follow-symlinks -i '/^[[:blank:]#]*AUTO_SETUP_NET_STATIC_MASK=/d' /boot/dietpi.txt
+
+ # Software updates, migrations and patches
+ if [[ -f '/boot/dietpi/.installed' ]]
+ then
# Pi-hole v6 migration
# - /etc/pihole/pihole.toml indicates that Pi-hole has been upgraded to v6 already.
# - The /var/www/pihole symlink indicates that an instance installed via dietpi-software has not been migrated yet.
diff --git a/.update/pre-patches b/.update/pre-patches
index 8d59ed3d9b..d5d0e58d87 100755
--- a/.update/pre-patches
+++ b/.update/pre-patches
@@ -389,14 +389,6 @@ if (( $G_DIETPI_VERSION_CORE < 9 || ( $G_DIETPI_VERSION_CORE == 9 && $G_DIETPI_V
then
if (( $G_HW_MODEL < 10 || ( $G_HW_MODEL == 75 && ${G_RASPBIAN:-0} == 1 ) )) || [[ -f '/etc/apt/sources.list.d/raspi.list' ]]
then
- G_DIETPI-NOTIFY 2 'Blocking conflicting Raspberry Pi desktop packages'
- # - https://github.com/MichaIng/DietPi/issues/1558#issuecomment-691206284
- # - https://github.com/MichaIng/DietPi/issues/4687
- G_EXEC eval 'cat << '\''_EOF_'\'' > /etc/apt/preferences.d/dietpi-raspberrypi
-Package: src:openbox src:obconf src:pcmanfm src:libfm src:gtk* src:lx*
-Pin: origin archive.raspberrypi.com
-Pin-Priority: -1
-_EOF_'
[[ -f '/etc/apt/preferences.d/dietpi-lxde' ]] && G_EXEC rm /etc/apt/preferences.d/dietpi-lxde
G_DIETPI-NOTIFY 2 'Updating Raspberry Pi APT repository list'
G_EXEC eval "echo 'deb https://archive.raspberrypi.com/debian ${G_DISTRO_NAME/forky/trixie} main' > /etc/apt/sources.list.d/raspi.list"
@@ -686,5 +678,22 @@ _EOF_"
fi
fi
+# v10.7
+if (( $G_DIETPI_VERSION_CORE < 10 || ( $G_DIETPI_VERSION_CORE == 10 && $G_DIETPI_VERSION_SUB < 7 ) ))
+then
+ if (( $G_HW_MODEL < 10 || ( $G_HW_MODEL == 75 && ${G_RASPBIAN:-0} == 1 ) )) || [[ -f '/etc/apt/sources.list.d/raspi.list' ]]
+ then
+ G_DIETPI-NOTIFY 2 'Blocking conflicting Raspberry Pi desktop packages'
+ # - https://github.com/MichaIng/DietPi/issues/1558#issuecomment-691206284
+ # - https://github.com/MichaIng/DietPi/issues/4687
+ # and cups-filters: https://github.com/MichaIng/DietPi/issues/8245
+ G_EXEC eval 'cat << '\''_EOF_'\'' > /etc/apt/preferences.d/dietpi-raspberrypi
+Package: src:cups-filters src:openbox src:obconf src:pcmanfm src:libfm src:gtk* src:lx*
+Pin: origin archive.raspberrypi.com
+Pin-Priority: -1
+_EOF_'
+ fi
+fi
+
exit 0
}
diff --git a/.update/version b/.update/version
index 4808f2cdfe..bebf0be975 100644
--- a/.update/version
+++ b/.update/version
@@ -2,8 +2,8 @@
# shellcheck disable=SC2034
# Available DietPi version
G_REMOTE_VERSION_CORE=10
-G_REMOTE_VERSION_SUB=6
-G_REMOTE_VERSION_RC=2
+G_REMOTE_VERSION_SUB=7
+G_REMOTE_VERSION_RC=0
# Minimum DietPi version to allow update
G_MIN_VERSION_CORE=8
G_MIN_VERSION_SUB=0
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index f0e4af6eb7..0436f1a427 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,3 +1,25 @@
+v10.7
+(2026-09-05)
+
+New images:
+
+New tools:
+- dietpi-network | The DietPi network configuration has gone through a rework. A new tool "dietpi-network" allows to configure multiple Ethernet(-like) and WiFi interfaces. This allows to e.g. configure one interface with gateway for Internet access, and another one with static IP and without gateway for LAN access. This works independently of the interface name, i.e. it does not need to be eth[0-9] or wlan[0-9], but the type is detected in other ways, which adds support for systemd's "predictable interface names", as well as virtual interfaces as provided in container guests. A CLI has been added to add, remove, or adjust individual interfaces. Configurations are stored in per-interface /etc/network/interfaces.d/.conf drop-in config files, and also automatically migrated from the previously used /etc/network/interfaces when applying changes. These changes are a basis to allow configuring more complex network setups, like bridges, NAT, and e.g. more flexible WiFi-to-WiFi hotspots.
+
+Enhancements:
+- DietPi-Banner | The Fail2Ban status now also counts bans for whole subnets in CIDR notation, which can be applied manually via fail2ban-client. The banner message now accordingly refers to "ban(s)" instead of "banned IP(s)".
+- DietPi-Software | Chromium: The low-end device mode flag and some other legacy flags, aiming to maximise Chromium performance at the cost of visual quality, have been removed from our config /etc/chromium.d/dietpi. These had some value at Raspberry Pi 1 times, but since some years, Chromium cannot be executed on ARMv6 SBCs anyway. For Chromium to be started as root, e.g. in some kind of minimal kiosk setup, the "--no-sandbox" flag is needed, and the "--test-type" flag hides a warning that skipping the sandbox is not recommended for security reasons. This is now applied only conditionally, if Chromium is really started as root user, otherwise sandboxing is used. Note that we generally do not recommend to start desktop sessions and GUI applications as root on a regular basis, and some, like Chromium and Mate, will throw respective warnings. Hence this is mainly aimed for direct Chromium starts from Linux console, where additional permissions are needed in any case, with trusted websites, like a fixed page in kiosk mode. Many thanks to @rmscode for making this a topic: https://dietpi.com/forum/t/25394
+
+Bug fixes:
+- Raspberry Pi | Resolved an issue where dtparam entries in config.txt were ineffective, if DRM/KMS was enabled. Any dtparam entry sorted after any dtoverlay entry, is gets applied to the overlay, rather than the base device tree, that way becoming ineffective, or change/break the overlay. This particularly started to cause issues since DietPi v10.5, when we added dtoverlay=vc4-kms-v3d as commented line into the display section of our default config.txt, above all dtparam lines. As fast as KMS/DRM is enabled, which uncomments the line, all dtparam entries become ineffective. Onboard HDMI audio on the first port couldn't be enabled along with KMS/DRM, since dtparam=audio=off (intended to disable the Broadcom analogue 3.5mm driver) got applied to dtoverlay=vc4-kms-v3d to become dtoverlay=vc4-kms-v3d,audio=off, which disables HDMI audio on the first HDMI port. Many thanks to @camrossi and @Infiltraitor for reporting this issue: https://github.com/MichaIng/DietPi/issues/8202, https://dietpi.com/forum/t/25411
+- Orange Pi 5/5B | Resolved a v10.5 regression where the USB 2.0 and Type-C ports were not functional, since we moved to mainline Linux where the respective device tree overlay changed its name. Without the overlay, they are running in OTG mode.
+- DietPi-Banner | Resolved an issue where the number of failed systemd services could not be obtained when logging in as non-root user, if D-Bus was not installed. Many thanks to @CA_Lobo for reporting this issue: https://dietpi.com/forum/t/25413
+- DietPi-Software | Ampache: Resolved an issue where detecting the latest version failed, since Ampache 8 requires PHP 8.5+. The latest version is now searched among all releases, so that latest Ampache 7 is downloaded on all supported Debian versions at time of writing.
+
+As always, many smaller code performance and stability improvements, visual and spelling fixes have been done, too much to list all of them here. Check out all code changes of this release on GitHub: https://github.com/MichaIng/DietPi/pull/XXXX
+
+-----------------------------------------------------------------------------------------------------------
+
v10.6
(2026-08-08)
@@ -8,7 +30,7 @@ New images:
Enhancements:
- Allwinner/Amlogic/Rockchip SBCs | A driver for certain ASUS USB keyboards has been added to all our kernel builds. Many thanks to @rouilj for reporting the issue with one of these: https://dietpi.com/forum/t/25290
- DietPi-Banner | Our login banner received a significant number of new features and enhancements: It is now possible to see disk space usage stats of any mounted drive, including path patterns for e.g. dynamic mounts. Failed systemd services and active Fail2Ban bans can be shown, as well as network RX/TX usage stats, not only for the default interface, but for all Ethernet, WiFi, and VPN interfaces of all network namespaces. Multiple custom command entries can now be added, which can make use of the colour code variables, which can be changed in the config file /boot/dietpi/.dietpi-banner. The number of colour codes has been extended, using easier to remember named array indices. Many thanks to @timjolson for implementing these features: https://github.com/MichaIng/DietPi/pull/8172
-- DietPi-Software | BirdNET-Go: The path to the ONNX runtime library is not set in (re)install to enable access to the additional bird classifier models. This can be also applied manually, following the instructions in the next link. Many thanks to @oradke for reporting this issue: https://github.com/MichaIng/DietPi/issues/8196
+- DietPi-Software | BirdNET-Go: The path to the ONNX runtime library is now set on (re)install to enable access to the additional bird classifier models. This can be also applied manually, following the instructions in the next link. Many thanks to @oradke for reporting this issue: https://github.com/MichaIng/DietPi/issues/8196
- DietPi-Software | Kubo: The IPFS Node install option has been enabled for RISC-V.
Bug fixes:
diff --git a/dietpi.txt b/dietpi.txt
index 241cf50b02..3a2010e6c6 100644
--- a/dietpi.txt
+++ b/dietpi.txt
@@ -33,10 +33,9 @@ AUTO_SETUP_NET_WIFI_ENABLED=0
# - NB: This choice may be overridden if the WiFi access point sends a country code.
AUTO_SETUP_NET_WIFI_COUNTRY_CODE=GB
-# Enter your static network details below, if applicable.
+# Enter your static network details below, if applicable. The netmask in CIDR notation is optional, and defaults to "/24".
AUTO_SETUP_NET_USESTATIC=0
-AUTO_SETUP_NET_STATIC_IP=192.168.0.100
-AUTO_SETUP_NET_STATIC_MASK=255.255.255.0
+AUTO_SETUP_NET_STATIC_IP=192.168.0.100/24
AUTO_SETUP_NET_STATIC_GATEWAY=192.168.0.1
AUTO_SETUP_NET_STATIC_DNS=9.9.9.9 149.112.112.112
diff --git a/dietpi/dietpi-config b/dietpi/dietpi-config
index a3c99da0ea..68930d67d9 100755
--- a/dietpi/dietpi-config
+++ b/dietpi/dietpi-config
@@ -82,7 +82,7 @@
4) TARGETMENUID=3;;
5) TARGETMENUID=7;;
6) TARGETMENUID=5;;
- 7) TARGETMENUID=8;;
+ 7) /boot/dietpi/dietpi-network;;
8) TARGETMENUID=16;;
9) /boot/dietpi/dietpi-autostart;;
10) TARGETMENUID=11;;
@@ -509,7 +509,6 @@ To set the final Linux console resolution, please use dietpi-display, or the Dis
)
(( $menu_index )) && G_WHIP_MENU_ARRAY[$menu_index]=${G_WHIP_MENU_ARRAY[$menu_index]/\[ \]/[X]}
- G_WHIP_BUTTON_CANCEL_TEXT='Back'
G_WHIP_DEFAULT_ITEM=${gpu_driver^}
G_WHIP_MENU 'Please select an option:' || { Back_or_Exit 1; return 0; } # Display Options
@@ -1492,1093 +1491,6 @@ If unsure, set any value, 'Ondemand Down Factor' option on the next screen will
esac
}
- NET_RX_BYTE=0
- NET_TX_BYTE=0
- NET_RX_MB='N/A'
- NET_TX_MB='N/A'
-
- # $1 = interface
- Net_Update_UsageStats()
- {
- local input=$1
-
- NET_RX_BYTE=0
- NET_TX_BYTE=0
- NET_RX_MB='N/A'
- NET_TX_MB='N/A'
-
- [[ -f /sys/class/net/$input/statistics/rx_bytes && -f /sys/class/net/$input/statistics/tx_bytes ]] || return
-
- read -r NET_RX_BYTE < "/sys/class/net/$input/statistics/rx_bytes"
- disable_error=1 G_CHECK_VALIDINT "$NET_RX_BYTE" 1 && NET_RX_MB="$(( $NET_RX_BYTE / 1024 / 1024 )) MiB"
- read -r NET_TX_BYTE < "/sys/class/net/$input/statistics/tx_bytes"
- disable_error=1 G_CHECK_VALIDINT "$NET_TX_BYTE" 1 && NET_TX_MB="$(( $NET_TX_BYTE / 1024 / 1024 )) MiB"
- }
-
- ETH_IP_STATIC='0.0.0.0'
- ETH_GATEWAY_STATIC='0.0.0.0'
- ETH_MASK_STATIC='0.0.0.0'
- ETH_DNS_STATIC='0.0.0.0'
- ETH_DEV_IFACE='eth0'
- ETH_DISABLED=0
- ETH_HARDWARE=0
- ETH_CONNECTED=0
- ETH_IP='0.0.0.0'
- ETH_GATEWAY='0.0.0.0'
- ETH_MASK='0.0.0.0'
- ETH_MODE=1 # 0=static 1=dhcp
- ETH_MODE_TARGET=0
-
- WIFI_IP_STATIC='0.0.0.0'
- WIFI_GATEWAY_STATIC='0.0.0.0'
- WIFI_MASK_STATIC='0.0.0.0'
- WIFI_DNS_STATIC='0.0.0.0'
- WIFI_DEV_IFACE='wlan0'
- WIFI_DISABLED=0
- WIFI_HARDWARE=0
- WIFI_CONNECTED=0
- WIFI_IP='0.0.0.0'
- WIFI_GATEWAY='0.0.0.0'
- WIFI_MASK='0.0.0.0'
- WIFI_MODE=1 # 0=static 1=dhcp
- WIFI_MODE_TARGET=0
- WIFI_SSID_CURRENT='Disconnected / No SSID'
- WIFI_BITRATE=0
- WIFI_SIGNALSTRENGTH=0
- WIFI_HOTSPOT=0
- WIFI_COUNTRYCODE='Unknown'
- WIFI_AUTO_RECONNECT_ACTIVE=0
-
- DNS_CURRENT='0.0.0.0'
-
- Network_ETH_CopyCurrentToStatic()
- {
- # Apply if we have a connection
- (( $ETH_CONNECTED )) || return 0
-
- ETH_IP_STATIC=$ETH_IP
- ETH_GATEWAY_STATIC=$ETH_GATEWAY
- ETH_MASK_STATIC=$ETH_MASK
- ETH_DNS_STATIC=$DNS_CURRENT
- }
-
- Network_WIFI_CopyCurrentToStatic()
- {
- # Apply if we have a connection
- (( $WIFI_CONNECTED )) || return 0
-
- WIFI_IP_STATIC=$WIFI_IP
- WIFI_GATEWAY_STATIC=$WIFI_GATEWAY
- WIFI_MASK_STATIC=$WIFI_MASK
- WIFI_DNS_STATIC=$DNS_CURRENT
- }
-
- Network_Restart()
- {
- # Stop WiFi hotspot
- (( $WIFI_HOTSPOT )) && G_EXEC systemctl stop isc-dhcp-server hostapd
-
- # Enable/Disable WiFi modules
- /boot/dietpi/func/dietpi-set_hardware wifimodules $(( ! $WIFI_DISABLED ))
-
- (( $WIFI_DISABLED )) && [[ $(dpkg-query -s 'iw' 'wpasupplicant' 'wireless-regdb' 2> /dev/null) ]] && G_WHIP_BUTTON_CANCEL_TEXT='Skip' G_WHIP_YESNO 'Would you like to purge all WiFi related APT packages?
- \nThis will free up space, but an internet-capable Ethernet connection is required to re-enable WiFi functionality.
- \nAffected packages: iw wpasupplicant wireless-regdb' && G_AGP 'iw' 'wpasupplicant' 'wireless-regdb'
-
- # Restart network
- G_DIETPI-NOTIFY 2 'Restarting network connections, please wait...'
- G_EXEC systemctl daemon-reload
- # - Ethernet
- if (( ! $ETH_DISABLED ))
- then
- journalctl -fn 0 -u "ifup@$ETH_DEV_IFACE" &
- G_EXEC_NOHALT=1 G_EXEC_OUTPUT=1 G_EXEC systemctl restart "ifup@$ETH_DEV_IFACE"
- kill -15 %%
- else
- ifdown --force "$ETH_DEV_IFACE" 2> /dev/null
- fi
- # - WiFi: Only try to configure if this is either a hotspot or an SSID has been configured
- if (( ! $WIFI_DISABLED )) && { (( $WIFI_HOTSPOT )) || grep -q '^network=' /etc/wpa_supplicant/wpa_supplicant.conf; }
- then
- journalctl -fn 0 -u "ifup@$WIFI_DEV_IFACE" &
- G_EXEC_NOHALT=1 G_EXEC_OUTPUT=1 G_EXEC systemctl restart "ifup@$WIFI_DEV_IFACE"
- kill -15 %%
- else
- ifdown --force "$WIFI_DEV_IFACE" 2> /dev/null
- fi
-
- # Start WiFi hotspot
- (( $WIFI_HOTSPOT )) && G_EXEC systemctl start hostapd isc-dhcp-server
-
- # Add a little delay to ensure all network device data are updated (eg: SSID current takes a little longer)
- G_DIETPI-NOTIFY 2 'Reloading networking data, please wait...'
- G_SLEEP 2
-
- # Update network data
- Network_GetData
-
- G_DIETPI-NOTIFY 0 'Network restarted'
- }
-
- Network_ApplyChanges()
- {
- # Check if resolvconf is available, else apply static DNS server via /etc/resolv.conf directly instead of /etc/network/interfaces entry
- local i resolvconf=0
- command -v resolvconf > /dev/null && resolvconf=1
- if (( ! $resolvconf ))
- then
- if (( ! $ETH_DISABLED && $ETH_MODE_TARGET == 0 ))
- then
- > /etc/resolv.conf
- for i in $ETH_DNS_STATIC; do echo "nameserver $i" >> /etc/resolv.conf; done
-
- elif (( ! $WIFI_DISABLED && $WIFI_MODE_TARGET == 0 ))
- then
- > /etc/resolv.conf
- for i in $WIFI_DNS_STATIC; do echo "nameserver $i" >> /etc/resolv.conf; done
- fi
- fi
-
- # Eth
- local eth_enabled_text=
- (( $ETH_DISABLED )) && eth_enabled_text='#'
- local eth_dhcp_static_text='dhcp'
- local eth_dns_text='#'
- if (( $ETH_MODE_TARGET == 0 ))
- then
- eth_dhcp_static_text='static'
- (( $resolvconf )) && eth_dns_text=
- fi
-
- # WiFi
- local wifi_enabled_text=
- (( $WIFI_DISABLED )) && wifi_enabled_text='#'
- local wifi_dhcp_static_text='dhcp'
- local wifi_dns_text='#'
- if (( $WIFI_MODE_TARGET == 0 ))
- then
- wifi_dhcp_static_text='static'
- (( $resolvconf )) && wifi_dns_text=
- fi
-
- # Create interface config
- local gateway="gateway $ETH_GATEWAY_STATIC"
- [[ $ETH_GATEWAY_STATIC ]] || gateway="#gateway ${ETH_IP_STATIC%.*}.1"
- cat << _EOF_ > /etc/network/interfaces
-# Location: /etc/network/interfaces
-# Please modify network settings via: dietpi-config
-# Or create your own drop-ins in: /etc/network/interfaces.d/
-
-# Drop-in configs
-source interfaces.d/*
-
-# Ethernet
-${eth_enabled_text}allow-hotplug $ETH_DEV_IFACE
-iface $ETH_DEV_IFACE inet $eth_dhcp_static_text
-address $ETH_IP_STATIC
-netmask $ETH_MASK_STATIC
-$gateway
-${eth_dns_text}dns-nameservers $ETH_DNS_STATIC
-
-# WiFi
-${wifi_enabled_text}allow-hotplug $WIFI_DEV_IFACE
-_EOF_
- # WiFi Hotspot
- if (( $WIFI_HOTSPOT )); then
-
- cat << _EOF_ >> /etc/network/interfaces
-iface $WIFI_DEV_IFACE inet static
-address $WIFI_IP_STATIC
-netmask $WIFI_MASK_STATIC
-#gateway 192.168.0.1
-#dns-nameservers 9.9.9.9 149.112.112.112
-pre-up iw dev $WIFI_DEV_IFACE set power_save off
-post-down iw dev $WIFI_DEV_IFACE set power_save on
-
-# iptables NAT rules
-up iptables-restore < /etc/iptables.ipv4.nat
-up ip6tables-restore < /etc/iptables.ipv6.nat
-_EOF_
- # - Alter hostapd and DHCP server configs
- G_CONFIG_INJECT 'interface=' "interface=$WIFI_DEV_IFACE" /etc/hostapd/hostapd.conf
- [[ -f '/etc/default/isc-dhcp-server' ]] && G_CONFIG_INJECT 'INTERFACESv4=' "INTERFACESv4=\"$WIFI_DEV_IFACE\"" /etc/default/isc-dhcp-server
-
- # WiFi client
- else
- gateway="gateway $WIFI_GATEWAY_STATIC"
- [[ $WIFI_GATEWAY_STATIC ]] || gateway="#gateway ${WIFI_IP_STATIC%.*}.1"
- cat << _EOF_ >> /etc/network/interfaces
-iface $WIFI_DEV_IFACE inet $wifi_dhcp_static_text
-address $WIFI_IP_STATIC
-netmask $WIFI_MASK_STATIC
-$gateway
-${wifi_dns_text}dns-nameservers $WIFI_DNS_STATIC
-pre-up iw dev $WIFI_DEV_IFACE set power_save off
-post-down iw dev $WIFI_DEV_IFACE set power_save on
-wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
-_EOF_
- fi
-
- # Remove wireless-power setting if not supported by adapter/firmware
- # shellcheck disable=SC2015
- (( $WIFI_HARDWARE )) && iw dev "$WIFI_DEV_IFACE" set power_save on 2> /dev/null && iw dev "$WIFI_DEV_IFACE" set power_save off 2> /dev/null || G_EXEC sed --follow-symlinks -i '/ iw dev .* set power_save /d' /etc/network/interfaces
-
- # Update WiFi db/wpa_supplicant if enabled
- (( $WIFI_DISABLED )) || /boot/dietpi/func/dietpi-wifidb 1
-
- # Update Current Mode for network restart
- ETH_MODE=$ETH_MODE_TARGET
- WIFI_MODE=$WIFI_MODE_TARGET
-
- # Restart network
- Network_Restart
- }
-
- # $1: Adapter type | 0=Eth, 1=WiFi
- Change_StaticIp()
- {
- # Ethernet
- if (( ! $1 ))
- then
- G_WHIP_DEFAULT_ITEM=$ETH_IP_STATIC
- G_WHIP_INPUTBOX 'Please enter a new static Ethernet IP address:' && ETH_IP_STATIC=$G_WHIP_RETURNED_VALUE
-
- # WiFi
- else
- G_WHIP_DEFAULT_ITEM=$WIFI_IP_STATIC
- G_WHIP_INPUTBOX 'Please enter a new static WiFi IP address:' && WIFI_IP_STATIC=$G_WHIP_RETURNED_VALUE
- fi
- }
-
- # $1: Adapter type | 0=Eth, 1=WiFi
- Change_StaticGateway()
- {
- # Ethernet
- if (( ! $1 ))
- then
- G_WHIP_DEFAULT_ITEM=$ETH_GATEWAY_STATIC
- G_WHIP_INPUTBOX 'Please enter a new static Ethernet gateway address:' && ETH_GATEWAY_STATIC=$G_WHIP_RETURNED_VALUE
-
- # WiFi
- else
- G_WHIP_DEFAULT_ITEM=$WIFI_GATEWAY_STATIC
- G_WHIP_INPUTBOX 'Please enter a new static WiFi gateway address:' && WIFI_GATEWAY_STATIC=$G_WHIP_RETURNED_VALUE
- fi
- }
-
- # $1: Adapter type | 0=Eth, 1=WiFi
- Change_StaticMask()
- {
- # Ethernet
- if (( ! $1 ))
- then
- G_WHIP_DEFAULT_ITEM=$ETH_MASK_STATIC
- G_WHIP_INPUTBOX 'Please enter a new static Ethernet network mask:' && ETH_MASK_STATIC=$G_WHIP_RETURNED_VALUE
-
- # WiFi
- else
- G_WHIP_DEFAULT_ITEM=$WIFI_MASK_STATIC
- G_WHIP_INPUTBOX 'Please enter a new static WiFi network mask:' && WIFI_MASK_STATIC=$G_WHIP_RETURNED_VALUE
- fi
- }
-
- # $1: Adapter type | 0=Eth, 1=WiFi
- Change_StaticDns()
- {
- # Current value => default choice
- (( $1 )) && G_WHIP_DEFAULT_ITEM=$WIFI_DNS_STATIC || G_WHIP_DEFAULT_ITEM=$ETH_DNS_STATIC
- G_WHIP_MENU_ARRAY=("$G_WHIP_DEFAULT_ITEM" ': Your current DNS server')
-
- # Auto detect local gateway(s)/router(s) to offer as DNS server(s).
- local gateway=$(ip r l 0/0 | mawk '{print $3}' ORS=' ')
- while [[ $gateway == *' '*' '* ]]; do gateway=${gateway% *}; done
- [[ $gateway ]] && G_WHIP_MENU_ARRAY+=("$gateway" ': Use local router as DNS server (recommended)')
-
- # Auto detect local DNS resolver to offer as system DNS
- ss -uln | grep -q ':53[[:blank:]]' && G_WHIP_MENU_ARRAY+=('127.0.0.1' ': Use local Pi-hole/AdGuard Home/Unbound (not recommended)')
-
- G_WHIP_MENU_ARRAY+=(
- 'Custom' ': Manually enter your DNS server'
- '' '●─ Public DNS providers '
- '1.1.1.1 1.0.0.1' ': Cloudflare'
- '9.9.9.9 149.112.112.112' ': Quad9'
- '8.8.8.8 8.8.4.4' ': Google'
- '208.67.222.222 208.67.220.220' ': OpenDNS'
- '209.244.0.3 209.244.0.4' ': Level3'
- '216.146.35.35 216.146.36.36' ': Dyn'
- '37.235.1.174 37.235.1.177' ': FreeDNS'
- '64.6.64.6 64.6.65.6' ': Verisign'
- '84.200.69.80 84.200.70.40' ': DNS.WATCH'
- )
-
- G_WHIP_MENU 'Please select a DNS server, or choose "Custom" for manual entry:' || return 0
-
- if [[ $G_WHIP_RETURNED_VALUE == 'Custom' ]]
- then
- (( $1 )) && G_WHIP_DEFAULT_ITEM=$WIFI_DNS_STATIC || G_WHIP_DEFAULT_ITEM=$ETH_DNS_STATIC
- G_WHIP_INPUTBOX "Please enter one or two space-separated DNS server addresses
- - E.g.: 9.9.9.9 149.112.112.112
- - Current: $G_WHIP_DEFAULT_ITEM" || return 0
- fi
-
- # Apply new value
- (( $1 )) && WIFI_DNS_STATIC=$G_WHIP_RETURNED_VALUE || ETH_DNS_STATIC=$G_WHIP_RETURNED_VALUE
- }
-
- Change_WifiCountryCode()
- {
- G_WHIP_MENU_ARRAY=(
-
- 'GB' ': Great Britain'
- 'DE' ': Germany'
- 'US' ': United States'
- 'JP' ': Japan'
- 'CN' ': China'
- 'IN' ': India'
- 'Manual' ': Enter a custom country code'
- )
-
- G_WHIP_DEFAULT_ITEM=$WIFI_COUNTRYCODE
- G_WHIP_MENU 'Please select your country to enable WiFi channels and power ratings allowed in your region.
-\nNB: Depending on your system, it may be required to disable and re-enable your WiFi connection for the change to take effect, or the kernel may override your choice with the info it gets from the access point. Verify that the correct code is returned by:
-# iw reg get' || return 0
-
- if [[ $G_WHIP_RETURNED_VALUE == 'Manual' ]]
- then
- local error
- G_WHIP_DEFAULT_ITEM=$WIFI_COUNTRYCODE
- until [[ $G_WHIP_RETURNED_VALUE == [[:upper:]][[:upper:]] ]]
- do
- G_WHIP_INPUTBOX "${error}Please enter a 2 capital letter country code: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2" || return 0
- error="[FAILED] Invalid country code ($G_WHIP_RETURNED_VALUE)\n\n"
- G_WHIP_DEFAULT_ITEM=$G_WHIP_RETURNED_VALUE
- done
- fi
- WIFI_COUNTRYCODE=$G_WHIP_RETURNED_VALUE
-
- /boot/dietpi/func/dietpi-set_hardware wificountrycode "$WIFI_COUNTRYCODE"
- }
-
- Wifi_Reconnect()
- {
- G_WHIP_YESNO 'WiFi will connect to the strongest configured SSID that is secure, with an open SSID being the last priority.\n
-Save all changes and restart networking?\n\nNB: All WiFi connections will be temporarily dropped!' && Network_ApplyChanges
- }
-
- Ethernet_Reconnect()
- {
- G_WHIP_YESNO 'Do you wish to apply settings and reconnect network now?\n
-NB: All Ethernet connections will be temporarily dropped!' && Network_ApplyChanges
- }
-
- INTERNET_TEST_STATE=0 # 0=not tested, 1=failed, 2=online
- INTERNET_TEST_URL='https://dietpi.com/'
-
- Network_GetData()
- {
- # Reset
- ETH_IP_STATIC=$(mawk '$1=="address"{print $2;exit}' /etc/network/interfaces)
- [[ $ETH_IP_STATIC ]] || ETH_IP_STATIC='192.168.0.100'
- ETH_GATEWAY_STATIC=$(mawk '$1=="gateway"{print $2;exit}' /etc/network/interfaces)
- [[ $ETH_GATEWAY_STATIC ]] || ETH_GATEWAY_STATIC='192.168.0.1'
- ETH_MASK_STATIC=$(mawk '$1=="netmask"{print $2;exit}' /etc/network/interfaces)
- [[ $ETH_MASK_STATIC ]] || ETH_MASK_STATIC='255.255.255.0'
- ETH_DNS_STATIC=$(mawk '$1=="dns-nameservers"{print $2,$3;exit}' /etc/network/interfaces)
- [[ $ETH_DNS_STATIC ]] || ETH_DNS_STATIC=$(mawk '$1=="nameserver"{print $2}' ORS=' ' /etc/resolv.conf)
- [[ $ETH_DNS_STATIC ]] || ETH_DNS_STATIC='9.9.9.9 149.112.112.112'
- # Remove trailing space in case of single nameserver, due to mawk '{print $2,$3}' respectively ORS=' '
- ETH_DNS_STATIC=${ETH_DNS_STATIC%[[:blank:]]}
- ETH_DEV_IFACE=$(G_GET_NET -q -t eth iface) || ETH_DEV_IFACE='eth0'
- ETH_DISABLED=$(( ! $(grep -Ecm1 "^[[:blank:]]*(allow-hotplug|auto)[[:blank:]]+$ETH_DEV_IFACE" /etc/network/interfaces) ))
- ETH_HARDWARE=0
- ETH_CONNECTED=0
- ETH_IP='0.0.0.0'
- ETH_GATEWAY='0.0.0.0'
- ETH_MASK='0.0.0.0'
- ETH_MODE=1
- ETH_MODE_TARGET=$ETH_MODE
-
- WIFI_IP_STATIC=$(mawk '$1=="address"{print $2}' /etc/network/interfaces | mawk 'NR==2')
- [[ $WIFI_IP_STATIC ]] || WIFI_IP_STATIC='192.168.0.100'
- WIFI_GATEWAY_STATIC=$(mawk '$1=="gateway"{print $2}' /etc/network/interfaces | mawk 'NR==2')
- [[ $WIFI_GATEWAY_STATIC ]] || WIFI_GATEWAY_STATIC='192.168.0.1'
- WIFI_MASK_STATIC=$(mawk '$1=="netmask"{print $2}' /etc/network/interfaces | mawk 'NR==2')
- [[ $WIFI_MASK_STATIC ]] || WIFI_MASK_STATIC='255.255.255.0'
- WIFI_DNS_STATIC=$(mawk '$1=="dns-nameservers"{print $2,$3}' /etc/network/interfaces | mawk 'NR==2')
- [[ $WIFI_DNS_STATIC ]] || WIFI_DNS_STATIC=$(mawk '$1=="nameserver"{print $2}' ORS=' ' /etc/resolv.conf)
- [[ $WIFI_DNS_STATIC ]] || WIFI_DNS_STATIC='9.9.9.9 149.112.112.112'
- # Remove trailing space in case of single nameserver, due to mawk '{print $2,$3}' respectively ORS=' '
- WIFI_DNS_STATIC=${WIFI_DNS_STATIC%[[:blank:]]}
- WIFI_DEV_IFACE=$(G_GET_NET -q -t wlan iface) || WIFI_DEV_IFACE='wlan0'
- WIFI_DISABLED=$(( ! $(grep -Ecm1 "^[[:blank:]]*(allow-hotplug|auto)[[:blank:]]+$WIFI_DEV_IFACE" /etc/network/interfaces) ))
- WIFI_HARDWARE=0
- WIFI_CONNECTED=0
- WIFI_IP='0.0.0.0'
- WIFI_GATEWAY='0.0.0.0'
- WIFI_MASK='0.0.0.0'
- WIFI_MODE=1
- WIFI_MODE_TARGET=$WIFI_MODE
-
- DNS_CURRENT=$(mawk '$1=="nameserver"{print $2}' ORS=' ' /etc/resolv.conf)
- DNS_CURRENT=${DNS_CURRENT% }
-
- # Reset extra WiFi stats
- WIFI_SSID_CURRENT='Disconnected / No SSID'
- WIFI_BITRATE=0
- WIFI_SIGNALSTRENGTH=0
- command -v hostapd > /dev/null && WIFI_HOTSPOT=1 || WIFI_HOTSPOT=0
- if (( $WIFI_HOTSPOT ))
- then
- WIFI_COUNTRYCODE=$(sed -n '/^[[:blank:]]*country_code=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)
-
- elif [[ -f '/etc/wpa_supplicant/wpa_supplicant.conf' ]]
- then
- WIFI_COUNTRYCODE=$(sed -n '/^[[:blank:]]*country=/{s/^[^=]*=//p;q}' /etc/wpa_supplicant/wpa_supplicant.conf)
- fi
- [[ ! $WIFI_COUNTRYCODE ]] && command -v iw > /dev/null && WIFI_COUNTRYCODE=$(iw reg get | mawk -F[\ :] '/country/{print $2;exit}')
- [[ $WIFI_COUNTRYCODE ]] || WIFI_COUNTRYCODE='00'
-
- # Convert CIDR integer to net mask, e.g. "192.168.0.100/24" (take "24") to "255.255.255.0"
- cidr2mask()
- {
- local i mask full_octets=$(( $1 / 8 )) partial_octet=$(( $1%8 ))
- for i in {0..3}
- do
- if (( $i < $full_octets ))
- then
- mask+='255'
-
- elif (( $i == $full_octets ))
- then
- mask+=$(( 256 - 2 ** ( 8 - $partial_octet ) ))
-
- else
- mask+='0'
- fi
- (( $i < 3 )) && mask+=.
- done
- echo "$mask"
- }
-
- # Eth
- if [[ -d /sys/class/net/$ETH_DEV_IFACE ]]; then
-
- # Hardware
- ETH_HARDWARE=1
-
- # Static or DHCP?
- ETH_MODE=$(grep -cm1 "iface $ETH_DEV_IFACE inet dhcp" /etc/network/interfaces)
- ETH_MODE_TARGET=$ETH_MODE
-
- # Connected and valid IP?
- ETH_CONNECTED=$(ip -o r l dev "$ETH_DEV_IFACE" | grep -vcm1 '[[:blank:]]linkdown')
-
- # Enabled and connected
- if (( ! $ETH_DISABLED && $ETH_CONNECTED )); then
-
- ETH_IP=$(ip -br -f inet a s "$ETH_DEV_IFACE" | mawk '{print $3}' | sed 's|/.*$||')
- ETH_GATEWAY=$(ip r l dev "$ETH_DEV_IFACE" 0/0 | mawk '{print $3;exit}')
- ETH_MASK=$(cidr2mask "$(ip -br -f inet a s "$ETH_DEV_IFACE" | mawk '{print $3}' | sed 's|^.*/||')")
-
- fi
-
- fi
-
- # WiFi
- if [[ -d /sys/class/net/$WIFI_DEV_IFACE ]]; then
-
- # Hardware
- WIFI_HARDWARE=1
-
- # Static or DHCP?
- WIFI_MODE=$(grep -cm1 "iface $WIFI_DEV_IFACE inet dhcp" /etc/network/interfaces)
- WIFI_MODE_TARGET=$WIFI_MODE
-
- # Connected and valid IP?
- WIFI_CONNECTED=$(ip -o r l dev "$WIFI_DEV_IFACE" | grep -vcm1 '[[:blank:]]linkdown')
-
- # Enabled and connected
- if (( ! $WIFI_DISABLED && $WIFI_CONNECTED )); then
-
- WIFI_IP=$(ip -br -f inet a s "$WIFI_DEV_IFACE" | mawk '{print $3}' | sed 's|/.*$||')
- WIFI_GATEWAY=$(ip r l dev "$WIFI_DEV_IFACE" 0/0 | mawk '{print $3;exit}')
- WIFI_MASK=$(cidr2mask "$(ip -br -f inet a s "$WIFI_DEV_IFACE" | mawk '{print $3}' | sed 's|^.*/||')")
-
- # Get extra WiFi stats
- WIFI_SSID_CURRENT=$(iw dev "$WIFI_DEV_IFACE" link | mawk '$1=="SSID:"{print $2}')
- WIFI_BITRATE=$(iw dev "$WIFI_DEV_IFACE" link | mawk '$1$2=="txbitrate:"{print $3;exit}')
- WIFI_SIGNALSTRENGTH=$(iw dev "$WIFI_DEV_IFACE" link | mawk '$1=="signal:"{print $2;exit}')
-
- # Try and detect if this is dBm (contains -) or %
- disable_error=1 G_CHECK_VALIDINT "$WIFI_SIGNALSTRENGTH" -500 -1 && WIFI_SIGNALSTRENGTH+=' dBm' || WIFI_SIGNALSTRENGTH+=' %'
-
- fi
-
- fi
- }
-
- # TARGETMENUID=8
- Menu_NetworkAdapters()
- {
- # Check Network
- Network_GetData
-
- # Obtain enabled/disabled status
- local eth_disabled_text='On'
- (( $ETH_DISABLED )) && eth_disabled_text='Off'
-
- local wlan_disabled_text='On'
- (( $WIFI_DISABLED )) && wlan_disabled_text='Off'
-
- # Obtain Hardware Status
- local eth_hardware_text='Available'
- (( $ETH_HARDWARE )) || eth_hardware_text='Not Found'
-
- local wlan_hardware_text='Available'
- (( $WIFI_HARDWARE )) || wlan_hardware_text='Not Found'
-
- # Obtain Connected/Carrier Status
- local eth_connected_text='Disconnected'
- (( $ETH_CONNECTED )) && eth_connected_text='Connected'
-
- local wlan_connected_text='Disconnected'
- if (( $WIFI_CONNECTED )); then
-
- (( $WIFI_HOTSPOT )) && wlan_connected_text='WiFi Hotspot Mode' || wlan_connected_text='Connected'
-
- fi
-
- # Internet Connection Status
- local Internet_connected_text='Run internet connection test'
- if (( $INTERNET_TEST_STATE == 2 )); then
-
- Internet_connected_text='[Success] | Online'
-
- elif (( $INTERNET_TEST_STATE == 1 )); then
-
- Internet_connected_text='[Failure] | Offline'
-
- fi
-
- # Proxy settings: Scrapes $http_proxy, otherwise obtains current values stored in dietpi.txt
- Load_Proxy_Vars
-
- local proxy_state_text='[Off]'
- (( $PROXY_ENABLED )) && proxy_state_text="[On] | $PROXY_ADDRESS:$PROXY_PORT"
-
- G_WHIP_MENU_ARRAY=('' '●─ Adapter Options ')
- G_WHIP_MENU_ARRAY+=('Ethernet' ": $eth_hardware_text | [$eth_disabled_text] | $eth_connected_text")
- G_WHIP_MENU_ARRAY+=('WiFi' ": $wlan_hardware_text | [$wlan_disabled_text] | $wlan_connected_text")
-
- # Onboard WiFi
- # - RPi 3/4/Zero W
- if (( $G_HW_ONBOARD_WIFI ))
- then
- local onboard_wifi_enabled=1
- if grep -q '^[[:blank:]]*dtoverlay=disable-wifi' /boot/firmware/config.txt
- then
- onboard_wifi_enabled=0
- G_WHIP_MENU_ARRAY+=('Onboard WiFi' ': [Off]')
- else
- G_WHIP_MENU_ARRAY+=('Onboard WiFi' ': [On]')
- fi
- fi
-
- G_WHIP_MENU_ARRAY+=('' '●─ Additional Options ')
-
- # IPv6
- if [[ -d '/proc/sys/net/ipv6' ]]
- then
- local ipv6_enabled=1 ipv6_status_text='On'
- grep -q '^[[:blank:]]*CONFIG_ENABLE_IPV6=0' /boot/dietpi.txt && ipv6_enabled=0 ipv6_status_text='Off'
- G_WHIP_MENU_ARRAY+=('IPv6' ": [$ipv6_status_text]")
- fi
-
- G_WHIP_MENU_ARRAY+=('Proxy' ": $proxy_state_text")
- G_WHIP_MENU_ARRAY+=('Test' ": $Internet_connected_text")
-
- G_WHIP_MENU 'Please select an option to change:' || { Back_or_Exit 0; return 0; } # Main menu
-
- case "$G_WHIP_RETURNED_VALUE" in
-
- 'Onboard WiFi')
-
- if (( $onboard_wifi_enabled )); then
-
- /boot/dietpi/func/dietpi-set_hardware wifimodules onboard_disable
-
- else
-
- /boot/dietpi/func/dietpi-set_hardware wifimodules onboard_enable
-
- fi
- REBOOT_REQUIRED=1
- ;;
-
- 'IPv6') /boot/dietpi/func/dietpi-set_hardware enableipv6 $(( ! $ipv6_enabled ));;
-
- 'Ethernet')
-
- # No adapter detected: Offer to disable if enabled
- if (( ! $ETH_HARDWARE ))
- then
- if (( ! $ETH_DISABLED ))
- then
- if G_WHIP_YESNO 'No Ethernet adapter was detected on your device.
-\nWould you like to disable Ethernet?\n - NB: Connections may drop!'
- then
- ETH_DISABLED=1
- Network_ApplyChanges
- fi
- return 0
- fi
- G_WHIP_MSG 'No Ethernet adapter was detected on your device.'
-
- # Disabled: Offer to enable
- elif (( $ETH_DISABLED ))
- then
- if G_WHIP_YESNO 'Ethernet must be enabled before settings can be changed.
-\nWould you like to enable Ethernet now?\n - NB: Connections may drop!'
- then
- ETH_DISABLED=0
- Network_ApplyChanges
- TARGETMENUID=9 # Ethernet adapter menu
- fi
- else
- TARGETMENUID=9 # Ethernet adapter menu
- fi
- ;;
-
- 'WiFi')
-
- # Disabled: Offer to enable, including WiFi modules for adapter to be detected
- if (( $WIFI_DISABLED ))
- then
- if G_WHIP_YESNO 'WiFi must be enabled before settings can be changed.
-\nWould you like to enable WiFi now?\n - NB: Connections may drop!'
- then
- WIFI_DISABLED=0
- Network_ApplyChanges
- # Enter submenu if WiFi adapter has been detected, else only preselect the menu entry
- (( $WIFI_HARDWARE )) && TARGETMENUID=10 || G_WHIP_DEFAULT_ITEM='WiFi' # WiFi adapter menu
- fi
-
- # No adapter detected: Offer to disable
- elif (( ! $WIFI_HARDWARE ))
- then
- if G_WHIP_YESNO 'No WiFi adapter was detected on your device.
-\nWould you like to disable WiFi?\n - NB: Connections may drop!'
- then
- WIFI_DISABLED=1
- Network_ApplyChanges
- fi
- else
- TARGETMENUID=10 # WiFi adapter menu
- fi
- ;;
-
- 'Test')
-
- G_WHIP_DEFAULT_ITEM=$INTERNET_TEST_URL
- if G_WHIP_INPUTBOX 'Please enter a URL address to test, e.g.: https://dietpi.com'; then
-
- INTERNET_TEST_URL=$G_WHIP_RETURNED_VALUE
-
- INTERNET_TEST_STATE=0 # Not tested
- if G_EXEC_NOHALT=1 G_CHECK_URL "$INTERNET_TEST_URL"; then
-
- INTERNET_TEST_STATE=2 # Online
-
- else
-
- INTERNET_TEST_STATE=1 # Failed
-
- fi
-
- fi
- ;;
-
- 'Proxy') TARGETMENUID=17;;
-
- *) :;;
-
- esac
- }
-
- # TARGETMENUID=9
- Menu_NetworkAdapters_Ethernet()
- {
- # Mode
- local mode_text='DHCP'
- (( $ETH_MODE_TARGET == 0 )) && mode_text='STATIC'
- G_WHIP_MENU_ARRAY=('' '●─ DHCP/STATIC IP ')
- G_WHIP_MENU_ARRAY+=('Change Mode' ": [$mode_text]")
-
- # Show static options
- if (( $ETH_MODE_TARGET == 0 ))
- then
- G_WHIP_MENU_ARRAY+=('Copy' ': Copy current address to "Static"')
- G_WHIP_MENU_ARRAY+=('Static IP' ": [$ETH_IP_STATIC]")
- G_WHIP_MENU_ARRAY+=('Static Mask' ": [$ETH_MASK_STATIC]")
- G_WHIP_MENU_ARRAY+=('Static Gateway' ": [$ETH_GATEWAY_STATIC]")
- G_WHIP_MENU_ARRAY+=('Static DNS' ": [$ETH_DNS_STATIC]")
- fi
-
- G_WHIP_MENU_ARRAY+=('' '●─ Additional Options ')
- local eth_speed='auto (default)'
- [[ -f '/etc/systemd/system/ethtool_force_speed.service' ]] && eth_speed=$(mawk '/^ExecStart=/{print $5;exit}' /etc/systemd/system/ethtool_force_speed.service)
- G_WHIP_MENU_ARRAY+=('Link Speed' ": [$eth_speed]")
- G_WHIP_MENU_ARRAY+=('Disable' ': Disable Ethernet adapter')
-
- G_WHIP_MENU_ARRAY+=('' '●─ Apply ')
- G_WHIP_MENU_ARRAY+=('Apply' ': Save all changes and restart networking')
-
- Net_Update_UsageStats "$ETH_DEV_IFACE"
-
- G_WHIP_DEFAULT_ITEM=$WHIP_SELECTION_PREVIOUS
- G_WHIP_MENU "Ethernet Details:\nUsage : Sent = $NET_TX_MB | Received = $NET_RX_MB\nAddress : IP = $ETH_IP | Mask = $ETH_MASK | Gateway = $ETH_GATEWAY | DNS = $DNS_CURRENT" || { Back_or_Exit 8; return 0; } # Network Options: Adapters
-
- WHIP_SELECTION_PREVIOUS=$G_WHIP_RETURNED_VALUE
-
- case "$G_WHIP_RETURNED_VALUE" in
-
- 'Change Mode') ETH_MODE_TARGET=$(( ! $ETH_MODE_TARGET ));;
-
- 'Link Speed')
-
- G_AG_CHECK_INSTALL_PREREQ ethtool
- G_WHIP_MENU_ARRAY=('0' ': Auto-negotiation (default, recommended)')
- while read -r speed
- do
- speed=${speed//[^0-9]}
- [[ $speed ]] && G_WHIP_MENU_ARRAY+=("$speed" ": Force $speed Mbit link speed")
-
- done < <(ethtool "$ETH_DEV_IFACE" | sed -n '/Supported link modes:/,/^[[:blank:]]*[[:alpha:]]/p' | head -n -1 | mawk '{print $NF}')
- G_WHIP_MENU 'Please select a supported Ethernet link speed to force or auto-negotiation.
-NB: Auto-negotiation is highly recommended as long as you do not have issues with the auto estimated link speed.
-This is mainly aimed at PINE A64 which may have a hardware issue that causes unstable 1000 Mbit link.' && /boot/dietpi/func/dietpi-set_hardware eth-forcespeed "$G_WHIP_RETURNED_VALUE"
- ;;
-
- 'Disable')
-
- if G_WHIP_YESNO 'Would you like to disable the Ethernet adapter?\n - (NOTICE) All Ethernet connections will be dropped.'; then
-
- ETH_DISABLED=1
- Network_ApplyChanges
- Back_or_Exit 8 # Network Options: Adapters
-
- fi
- ;;
-
- 'Apply') Ethernet_Reconnect;;
-
- 'Copy') Network_ETH_CopyCurrentToStatic;;
-
- 'Static IP') Change_StaticIp 0;;
-
- 'Static Gateway') Change_StaticGateway 0;;
-
- 'Static Mask') Change_StaticMask 0;;
-
- 'Static DNS') Change_StaticDns 0;;
-
- *) :;;
-
- esac
- }
-
- HOTSPOT_SSID=
- HOTSPOT_KEY=
- HOTSPOT_CHANNEL=
- HOTSPOT_WIFI4=0
- HOTSPOT_WIFI5=0
- HOTSPOT_WIFI6=0
- HOTSPOT_5G=0
- HOTSPOT_5G_CHANNEL=
-
- # TARGETMENUID=10
- Menu_NetworkAdapters_Wifi()
- {
- Net_Update_UsageStats "$WIFI_DEV_IFACE"
-
- local description_text="WiFi Details:\nUsage : Sent = $NET_TX_MB | Received = $NET_RX_MB\n"
-
- G_WHIP_MENU_ARRAY=('' '●─ Basic Options ')
-
- # WiFi Hotspot menu
- if (( $WIFI_HOTSPOT ))
- then
- # Status and toggle
- local hotspot_active_state=0 hotspot_active_state_text='[Off] | Select to turn on hotspot'
- systemctl -q is-active hostapd && hotspot_active_state=1 hotspot_active_state_text='[On] | Select to turn off hotspot' description_text+='Status : Online' || description_text+='Status : Offline'
-
- # Load details into global vars, once
- if [[ ! $HOTSPOT_SSID ]]
- then
- HOTSPOT_SSID=$(sed -n '/^[[:blank:]]*ssid=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)
- HOTSPOT_KEY=$(sed -n '/^[[:blank:]]*wpa_passphrase=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)
- HOTSPOT_WIFI4=$(grep -cm1 '^[[:blank:]]*ieee80211n=1$' /etc/hostapd/hostapd.conf)
- HOTSPOT_WIFI5=$(grep -cm1 '^[[:blank:]]*ieee80211ac=1$' /etc/hostapd/hostapd.conf)
- HOTSPOT_WIFI6=$(grep -cm1 '^[[:blank:]]*ieee80211ax=1$' /etc/hostapd/hostapd.conf)
- HOTSPOT_5G=$(grep -cm1 '^[[:blank:]]*hw_mode=a$' /etc/hostapd/hostapd.conf)
- if (( $HOTSPOT_5G ))
- then
- HOTSPOT_5G_CHANNEL=$(sed -n '/^[[:blank:]]*channel=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)
- else
- HOTSPOT_CHANNEL=$(sed -n '/^[[:blank:]]*channel=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)
- fi
- fi
-
- # WiFi 4 and WiFi 5 support status text
- local hotspot_n_text='Off' hotspot_ac_text='Off' hotspot_ax_text='Off' hotspot_freq_text='2.4' hotspot_channel_text
- (( $HOTSPOT_WIFI4 )) && hotspot_n_text='On'
- (( $HOTSPOT_WIFI5 )) && hotspot_ac_text='On'
- (( $HOTSPOT_WIFI6 )) && hotspot_ax_text='On'
- if (( $HOTSPOT_5G ))
- then
- hotspot_freq_text='5'
- [[ $HOTSPOT_5G_CHANNEL ]] || HOTSPOT_5G_CHANNEL=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_5G_CHANNEL=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
- [[ $HOTSPOT_5G_CHANNEL ]] || HOTSPOT_5G_CHANNEL=36
- hotspot_channel_text=$HOTSPOT_5G_CHANNEL
- else
- [[ $HOTSPOT_CHANNEL ]] || HOTSPOT_CHANNEL=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_CHANNEL=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
- [[ $HOTSPOT_CHANNEL ]] || HOTSPOT_CHANNEL=3
- hotspot_channel_text=$HOTSPOT_CHANNEL
- fi
-
- G_WHIP_MENU_ARRAY+=(
- 'SSID' ": [$HOTSPOT_SSID]"
- 'Key' ": [$HOTSPOT_KEY]"
- 'Frequency' ": [$hotspot_freq_text GHz]"
- 'Channel' ": [$hotspot_channel_text]"
- '802.11n' ": [$hotspot_n_text] WiFi 4 support"
- '802.11ac' ": [$hotspot_ac_text] WiFi 5 support"
- '802.11ax' ": [$hotspot_ax_text] WiFi 6 support"
- )
-
- # WiFi menu
- else
- description_text+="SSID : $WIFI_SSID_CURRENT | $WIFI_BITRATE Mbit | Strength: $WIFI_SIGNALSTRENGTH\nAddress : IP = $WIFI_IP | Mask = $WIFI_MASK | Gateway = $WIFI_GATEWAY | DNS = $DNS_CURRENT"
-
- G_WHIP_MENU_ARRAY+=('Scan' ': Scan and configure SSID')
-
- # Auto Reconnect / WiFi monitor
- local wifi_auto_reconnect_text='Off'
- systemctl -q is-active dietpi-wifi-monitor && WIFI_AUTO_RECONNECT_ACTIVE=1 wifi_auto_reconnect_text='On' || WIFI_AUTO_RECONNECT_ACTIVE=0
- (( $WIFI_CONNECTED || $WIFI_AUTO_RECONNECT_ACTIVE )) && G_WHIP_MENU_ARRAY+=('Auto Reconnect' ": [$wifi_auto_reconnect_text]")
-
- # Mode
- local mode_text='DHCP'
- (( $WIFI_MODE_TARGET )) || mode_text='STATIC'
- G_WHIP_MENU_ARRAY+=(
- '' '●─ DHCP/STATIC IP '
- 'Change Mode' ": [$mode_text]"
- )
-
- # Show static options
- (( $WIFI_MODE_TARGET == 0 )) && G_WHIP_MENU_ARRAY+=(
- 'Copy' ': Copy current address to "Static"'
- 'Static IP' ": [$WIFI_IP_STATIC]"
- 'Static Mask' ": [$WIFI_MASK_STATIC]"
- 'Static Gateway' ": [$WIFI_GATEWAY_STATIC]"
- 'Static DNS' ": [$WIFI_DNS_STATIC]"
- )
- fi
-
- # Country code
- G_WHIP_MENU_ARRAY+=('' '●─ Additional Options ')
- if [[ $WIFI_COUNTRYCODE == '00' ]]
- then
- G_WHIP_MENU_ARRAY+=('Country' ": [$WIFI_COUNTRYCODE] (Not set, please configure)")
- else
- G_WHIP_MENU_ARRAY+=('Country' ": [$WIFI_COUNTRYCODE]")
- fi
-
- G_WHIP_MENU_ARRAY+=('' '●─ Toggle State ')
- if (( $WIFI_HOTSPOT ))
- then
- G_WHIP_MENU_ARRAY+=('State' ": $hotspot_active_state_text")
- else
- G_WHIP_MENU_ARRAY+=('Disable' ': Disable WiFi adapter')
- fi
-
- G_WHIP_MENU_ARRAY+=(
- '' '●─ Apply '
- 'Apply' ': Save all changes and restart networking'
- )
-
- G_WHIP_DEFAULT_ITEM=$WHIP_SELECTION_PREVIOUS
- G_WHIP_MENU "$description_text" || { Back_or_Exit 8; return 0; } # Network Options: Adapters
-
- WHIP_SELECTION_PREVIOUS=$G_WHIP_RETURNED_VALUE
-
- case "$G_WHIP_RETURNED_VALUE" in
-
- 'Auto Reconnect')
-
- if (( $WIFI_AUTO_RECONNECT_ACTIVE ))
- then
- G_EXEC systemctl disable --now dietpi-wifi-monitor
- else
- G_EXEC systemctl enable --now dietpi-wifi-monitor
- fi
- ;;
-
- 'Key')
-
- local error
- G_WHIP_DEFAULT_ITEM=$HOTSPOT_KEY
- until (( ${#G_WHIP_RETURNED_VALUE} > 7 ))
- do
- G_WHIP_INPUTBOX "${error}Please enter a key/password with a minimum of 8 characters for your WiFi hotspot:" || return 0
- error='[FAILED] The entered key is too short.\n\n'
- G_WHIP_DEFAULT_ITEM=$G_WHIP_RETURNED_VALUE
- done
- HOTSPOT_KEY=$G_WHIP_RETURNED_VALUE
- ;;
-
- 'SSID')
-
- G_WHIP_DEFAULT_ITEM=$HOTSPOT_SSID
- G_WHIP_INPUTBOX 'Please enter an SSID for your WiFi hotspot:' && HOTSPOT_SSID=$G_WHIP_RETURNED_VALUE
- ;;
-
- 'Channel')
-
- if (( $HOTSPOT_5G ))
- then
- G_WHIP_DEFAULT_ITEM=$HOTSPOT_5G_CHANNEL
- G_WHIP_INPUTBOX 'Please enter a 5 GHz WiFi channel for your hotspot.
-\nA full list of supported 5 GHz WiFi channels per region can be found e.g. on Wikipedia: https://en.wikipedia.org/wiki/List_of_WLAN_channels#5_GHz_(802.11a/h/n/ac/ax)' && HOTSPOT_5G_CHANNEL=$G_WHIP_RETURNED_VALUE
- else
- local channel_mhz=2412 channel_min=1 channel_max=13
- G_WHIP_MENU_ARRAY=()
- for ((i=$channel_min; i<=$channel_max; i++))
- do
- G_WHIP_MENU_ARRAY+=("$i" ": $channel_mhz MHz")
- ((channel_mhz+=5))
- done
-
- G_WHIP_DEFAULT_ITEM=$HOTSPOT_CHANNEL
- G_WHIP_MENU 'Please select a 2.4 GHz WiFi channel for your hotspot:' && HOTSPOT_CHANNEL=$G_WHIP_RETURNED_VALUE
- fi
- ;;
-
- '802.11n')
-
- HOTSPOT_WIFI4=$(( ! $HOTSPOT_WIFI4 ))
- # 5 GHz requires at least WiFi 4
- (( $HOTSPOT_WIFI4 || $HOTSPOT_WIFI5 || $HOTSPOT_WIFI6 )) || HOTSPOT_5G=0
- ;;
-
- '802.11ac')
-
- HOTSPOT_WIFI5=$(( ! $HOTSPOT_WIFI5 ))
- # WiFi 5 implies 5 GHz
- (( $HOTSPOT_WIFI5 )) && HOTSPOT_5G=1
- # 5 GHz requires at least WiFi 4
- (( $HOTSPOT_WIFI4 || $HOTSPOT_WIFI5 || $HOTSPOT_WIFI6 )) || HOTSPOT_5G=0
- ;;
-
- '802.11ax')
-
- HOTSPOT_WIFI6=$(( ! $HOTSPOT_WIFI6 ))
- # 5 GHz requires at least WiFi 4
- (( $HOTSPOT_WIFI4 || $HOTSPOT_WIFI5 || $HOTSPOT_WIFI6 )) || HOTSPOT_5G=0
- ;;
-
- 'Frequency')
-
- HOTSPOT_5G=$(( ! $HOTSPOT_5G ))
- # 5 GHz requires at least WiFi 4
- (( $HOTSPOT_5G && ! $HOTSPOT_WIFI5 && ! $HOTSPOT_WIFI6 )) && HOTSPOT_WIFI4=1
- ;;
-
- 'Country') Change_WifiCountryCode;;
-
- 'Disable')
-
- G_WHIP_YESNO 'Would you like to disable the WiFi adapter?\n - (NOTICE) All WiFi connections will be dropped.' || return 0
- WIFI_DISABLED=1
- G_EXEC systemctl disable --now dietpi-wifi-monitor
- Network_ApplyChanges
- Back_or_Exit 8 # Network Options: Adapters
- ;;
-
- 'Scan') /boot/dietpi/func/dietpi-wifidb;;
-
- 'Change Mode')
-
- WIFI_MODE_TARGET=$(( ! $WIFI_MODE_TARGET ))
- [[ $WIFI_MODE_TARGET == 0 ]] && G_WHIP_MSG 'Information for STATIC IP:\n\nWhen using STATIC IP, please ensure only 1 SSID entry exists in the "Scan" menu. Else, WiFi will most likely fail, and, the IP conflict committee will be displeased ;)'
- ;;
-
- 'Apply')
-
- if (( $WIFI_HOTSPOT ))
- then
- # Update dietpi.txt
- G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_SSID=' "SOFTWARE_WIFI_HOTSPOT_SSID=$HOTSPOT_SSID" /boot/dietpi.txt
- GCI_PASSWORD=1 G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_KEY=' "SOFTWARE_WIFI_HOTSPOT_KEY=$HOTSPOT_KEY" /boot/dietpi.txt
- G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_CHANNEL=' "SOFTWARE_WIFI_HOTSPOT_CHANNEL=$HOTSPOT_CHANNEL" /boot/dietpi.txt
- G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_WIFI4=' "SOFTWARE_WIFI_HOTSPOT_WIFI4=$HOTSPOT_WIFI4" /boot/dietpi.txt
- G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_WIFI5=' "SOFTWARE_WIFI_HOTSPOT_WIFI5=$HOTSPOT_WIFI5" /boot/dietpi.txt
- G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_WIFI6=' "SOFTWARE_WIFI_HOTSPOT_WIFI6=$HOTSPOT_WIFI6" /boot/dietpi.txt
- G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_5G=' "SOFTWARE_WIFI_HOTSPOT_5G=$HOTSPOT_5G" /boot/dietpi.txt
- G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_5G_CHANNEL=' "SOFTWARE_WIFI_HOTSPOT_5G_CHANNEL=$HOTSPOT_5G_CHANNEL" /boot/dietpi.txt
-
- # Update hostapd.conf
- G_CONFIG_INJECT 'ssid=' "ssid=$HOTSPOT_SSID" /etc/hostapd/hostapd.conf
- G_CONFIG_INJECT 'wpa_passphrase=' "wpa_passphrase=$HOTSPOT_KEY" /etc/hostapd/hostapd.conf
- G_CONFIG_INJECT 'ieee80211n=' "ieee80211n=$HOTSPOT_WIFI4" /etc/hostapd/hostapd.conf
- G_CONFIG_INJECT 'ieee80211ac=' "ieee80211ac=$HOTSPOT_WIFI5" /etc/hostapd/hostapd.conf
- G_CONFIG_INJECT 'ieee80211ax=' "ieee80211ax=$HOTSPOT_WIFI6" /etc/hostapd/hostapd.conf '^ieee80211ac'
- if (( $HOTSPOT_WIFI4 || $HOTSPOT_WIFI5 || $HOTSPOT_WIFI6 ))
- then
- G_CONFIG_INJECT 'wmm_enabled=' 'wmm_enabled=1' /etc/hostapd/hostapd.conf
- else
- G_CONFIG_INJECT 'wmm_enabled=' 'wmm_enabled=0' /etc/hostapd/hostapd.conf
- fi
- if (( $HOTSPOT_5G ))
- then
- G_CONFIG_INJECT 'hw_mode=' 'hw_mode=a' /etc/hostapd/hostapd.conf
- G_CONFIG_INJECT 'channel=' "channel=$HOTSPOT_5G_CHANNEL" /etc/hostapd/hostapd.conf
- else
- G_CONFIG_INJECT 'hw_mode=' 'hw_mode=g' /etc/hostapd/hostapd.conf
- G_CONFIG_INJECT 'channel=' "channel=$HOTSPOT_CHANNEL" /etc/hostapd/hostapd.conf
- fi
-
- # Apply/Restart network
- Network_ApplyChanges
- else
- Wifi_Reconnect
- fi
- ;;
-
- 'Copy') Network_WIFI_CopyCurrentToStatic;;
-
- 'Static IP') Change_StaticIp 1;;
-
- 'Static Gateway') Change_StaticGateway 1;;
-
- 'Static Mask') Change_StaticMask 1;;
-
- 'Static DNS') Change_StaticDns 1;;
-
- 'State')
-
- if (( $hotspot_active_state ))
- then
- G_EXEC systemctl stop hostapd
- else
- G_EXEC systemctl start hostapd
- fi
- ;;
-
- *) :;;
- esac
- }
-
# TARGETMENUID=11
Menu_Tools()
{
@@ -3507,116 +2419,6 @@ NB: If you need to use *.pool.ntp.org servers, enter the base domain only. The s
esac
}
- PROXY_ENABLED=0
- PROXY_ADDRESS=
- PROXY_PORT=
- PROXY_USERNAME=
- PROXY_PASSWORD=
-
- # So we can call this in other menus (eg: submenu of this)
- Load_Proxy_Vars()
- {
- # Satisfy shellcheck
- [[ $http_proxy ]] || http_proxy=
-
- if [[ -f '/etc/bashrc.d/dietpi-proxy.sh' ]]
- then
- PROXY_ENABLED=1
- # shellcheck disable=SC1091
- . /etc/bashrc.d/dietpi-proxy.sh
- else
- PROXY_ENABLED=0
- # Inform user if DietPi proxy state does not match variable existence
- # - This occurs either because of missing reboot/login after exiting script before, or, proxy was set up outside of DietPi scripts
- # - Prompt only when inside/entering proxy settings
- [[ $http_proxy && $TARGETMENUID == 17 ]] && G_WHIP_MSG 'Either a proxy was set up outside of DietPi scripts or you need to reload you current login session (logout+login or reboot) for changes to take effect.'
- fi
-
- if [[ $http_proxy ]]
- then
- PROXY_ADDRESS=${http_proxy#*//}; PROXY_ADDRESS=${PROXY_ADDRESS%:*}
- PROXY_PORT=${http_proxy##*:}
- [[ $http_proxy == *'@'* ]] || return 0
- PROXY_ADDRESS=${PROXY_ADDRESS#*@}
- PROXY_USERNAME=${http_proxy#*//}; PROXY_USERNAME=${PROXY_USERNAME%%:*}
- PROXY_PASSWORD=${http_proxy%%@*}; PROXY_PASSWORD=${PROXY_PASSWORD##*:}
- else
- [[ $PROXY_ADDRESS ]] || PROXY_ADDRESS=$(sed -n '/^[[:blank:]]*CONFIG_PROXY_ADDRESS=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
- [[ $PROXY_PORT ]] || PROXY_PORT=$(sed -n '/^[[:blank:]]*CONFIG_PROXY_PORT=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
- [[ $PROXY_USERNAME ]] || PROXY_USERNAME=$(sed -n '/^[[:blank:]]*CONFIG_PROXY_USERNAME=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
- [[ $PROXY_PASSWORD ]] || PROXY_PASSWORD=$(sed -n '/^[[:blank:]]*CONFIG_PROXY_PASSWORD=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
- fi
- }
-
- # TARGETMENUID=17
- Menu_NetworkAdapters_Proxy()
- {
- Load_Proxy_Vars
-
- local proxy_state_text='Off'
- (( $PROXY_ENABLED )) && proxy_state_text='On'
-
- G_WHIP_MENU_ARRAY=(
-
- 'State' ": [$proxy_state_text]"
- 'Address' ": [$PROXY_ADDRESS]"
- 'Port' ": [$PROXY_PORT]"
- 'Username' ": [$PROXY_USERNAME]"
- 'Password' ": [$PROXY_PASSWORD]"
- )
-
- G_WHIP_BUTTON_OK_TEXT='Select' G_WHIP_MENU 'Please select an option to adjust. Logout and login for changes to take effect.' || { Back_or_Exit 8; return 0; } # Network Options: Adapters
-
- case "$G_WHIP_RETURNED_VALUE" in
-
- 'State') (( $PROXY_ENABLED )) && PROXY_ENABLED=0 || PROXY_ENABLED=1;;
-
- 'Address')
-
- G_WHIP_DEFAULT_ITEM=$PROXY_ADDRESS
- G_WHIP_INPUTBOX 'Please enter the proxy URL or IP address\n - eg: MyProxy.com' && PROXY_ADDRESS=$G_WHIP_RETURNED_VALUE || return 0
- G_CONFIG_INJECT 'CONFIG_PROXY_ADDRESS=' "CONFIG_PROXY_ADDRESS=$PROXY_ADDRESS" /boot/dietpi.txt
- ;;
-
- 'Port')
-
- G_WHIP_DEFAULT_ITEM=$PROXY_PORT
- G_WHIP_INPUTBOX 'Please enter the proxy port number\n - eg: 1234' && PROXY_PORT=$G_WHIP_RETURNED_VALUE || return 0
- G_CONFIG_INJECT 'CONFIG_PROXY_PORT=' "CONFIG_PROXY_PORT=$PROXY_PORT" /boot/dietpi.txt
- ;;
-
- 'Username')
-
- G_WHIP_DEFAULT_ITEM=$PROXY_USERNAME
- G_WHIP_INPUTBOX_REGEX='.*' G_WHIP_INPUTBOX 'Please enter the proxy username\n - eg: JoeBloggs\n - Leave blank if not required' && PROXY_USERNAME=$G_WHIP_RETURNED_VALUE || return 0
- G_CONFIG_INJECT 'CONFIG_PROXY_USERNAME=' "CONFIG_PROXY_USERNAME=$PROXY_USERNAME" /boot/dietpi.txt
- ;;
-
- 'Password')
-
- G_WHIP_DEFAULT_ITEM=$PROXY_PASSWORD
- G_WHIP_INPUTBOX_REGEX='.*' G_WHIP_INPUTBOX 'Please enter the proxy password\n - eg: LetMeIn\n - Leave blank if not required' && PROXY_PASSWORD=$G_WHIP_RETURNED_VALUE || return 0
- G_CONFIG_INJECT 'CONFIG_PROXY_PASSWORD=' "CONFIG_PROXY_PASSWORD=$PROXY_PASSWORD" /boot/dietpi.txt
- ;;
-
- *) return 0;;
- esac
-
- # Add export settings
- if (( $PROXY_ENABLED ))
- then
- if [[ $PROXY_USERNAME && $PROXY_PASSWORD ]]
- then
- echo "export {http,https,ftp}_proxy='http://$PROXY_USERNAME:$PROXY_PASSWORD@$PROXY_ADDRESS:$PROXY_PORT'" > /etc/bashrc.d/dietpi-proxy.sh
- else
- echo "export {http,https,ftp}_proxy='http://$PROXY_ADDRESS:$PROXY_PORT'" > /etc/bashrc.d/dietpi-proxy.sh
- fi
- else
- [[ -f '/etc/bashrc.d/dietpi-proxy.sh' ]] && G_EXEC rm /etc/bashrc.d/dietpi-proxy.sh
- unset -v {http,https,ftp}_proxy # Has no effect on current login session but for this script, e.g. connection test
- fi
- }
-
#/////////////////////////////////////////////////////////////////////////////////////
# Main Loop
#/////////////////////////////////////////////////////////////////////////////////////
@@ -3638,15 +2440,11 @@ NB: If you need to use *.pool.ntp.org servers, enter the base domain only. The s
5) Menu_SecurityOptions;;
6) Menu_GpumemoryOptions;;
7) Menu_LanguageOptions;;
- 8) Menu_NetworkAdapters;;
- 9) Menu_NetworkAdapters_Ethernet;;
- 10) Menu_NetworkAdapters_Wifi;;
11) Menu_Tools;;
13) Menu_Overclock;;
14) Menu_AudioOptions;;
15) Menu_StressTest;;
16) Menu_NetworkMisc;;
- 17) Menu_NetworkAdapters_Proxy;;
18) Menu_AdvancedOptions_Serial_UART;;
19) Menu_AdvancedOptions_APT;;
20) Menu_NetworkMisc_TestIPv4;;
diff --git a/dietpi/dietpi-drive_manager b/dietpi/dietpi-drive_manager
index a0a312c517..b075a19836 100755
--- a/dietpi/dietpi-drive_manager
+++ b/dietpi/dietpi-drive_manager
@@ -473,14 +473,14 @@ _EOF_
then
if (( ! ${aDRIVE_ISMOUNTED[$MENU_DRIVE_SELECTED]} ))
then
- G_EXEC_NOEXIT=1 G_EXEC mkdir -p /tmp/temporary_f2fs_mountpoint || return 1
- G_EXEC_NOEXIT=1 G_EXEC mount "$MENU_DRIVE_SELECTED" /tmp/temporary_f2fs_mountpoint || return 1
+ G_EXEC_NOEXIT=1 G_EXEC mkdir -p /tmp/temporary_btrfs_mountpoint || return 1
+ G_EXEC_NOEXIT=1 G_EXEC mount "$MENU_DRIVE_SELECTED" /tmp/temporary_btrfs_mountpoint || return 1
fi
G_EXEC_NOEXIT=1 G_EXEC btrfs filesystem resize max "${aDRIVE_MOUNT_TARGET[$MENU_DRIVE_SELECTED]}"
if (( ! ${aDRIVE_ISMOUNTED[$MENU_DRIVE_SELECTED]} ))
then
- G_EXEC_NOEXIT=1 G_EXEC umount /tmp/temporary_f2fs_mountpoint
- G_EXEC_NOEXIT=1 G_EXEC rmdir /tmp/temporary_f2fs_mountpoint
+ G_EXEC_NOEXIT=1 G_EXEC umount /tmp/temporary_btrfs_mountpoint
+ G_EXEC_NOEXIT=1 G_EXEC rmdir /tmp/temporary_btrfs_mountpoint
fi
fi
Init_Drives_and_Refresh
diff --git a/dietpi/dietpi-login b/dietpi/dietpi-login
index 5044c3ac64..c82c7b123c 100755
--- a/dietpi/dietpi-login
+++ b/dietpi/dietpi-login
@@ -69,7 +69,7 @@
do
(( $count > $timeout )) && { echo '[FAILED] Waiting for MPD FIFO timed out. Aborting...'; return 1; }
echo "[ INFO ] Waiting for MPD FIFO before starting CAVA ($count/$timeout)"
- sleep 1
+ G_SLEEP 1
((count++))
done
diff --git a/dietpi/dietpi-network b/dietpi/dietpi-network
new file mode 100755
index 0000000000..1ea71539c2
--- /dev/null
+++ b/dietpi/dietpi-network
@@ -0,0 +1,1319 @@
+#!/bin/bash
+{
+# --------------------------------------------
+# dietpi-network
+# Manage network interfaces and global network settings
+# --------------------------------------------
+# Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com
+# Updated by MichaIng / micha@dietpi.com / dietpi.com
+# Refactored by GitHub Copilot / github.com
+# --------------------------------------------
+# Location: /boot/dietpi/dietpi-network
+readonly USAGE='
+Usage: dietpi-network []
+Available commands:
+ , main Open the interactive top-level menu to control network settings
+ Open the interactive submenu for network interface
+ country Open the interactive WiFi country code submenu
+ proxy Open the interactive proxy submenu
+ apply [...] Apply interface config for and reconnect only that interface
+ remove Remove the DietPi drop-in config for and ifdown the interface
+ proxy enable|disable Enable or disable the configured proxy globally
+ proxy address|port|username|password
+ Apply to the specified proxy setting
+Available options for "apply" command:
+ --enable|--disable Enable or disable the interface
+ --dhcp|--static Select DHCP or static IPv4 mode
+ --ip [/] Static IPv4 address with optional CIDR netmask, else /24
+ --gateway Static IPv4 gateway
+ --dns " [...]" Static DNS server list
+ --copy-current Copy current live IPv4/DNS values into static settings before applying
+ --hotplug|--auto Bring up interface once detected/plugged (hotplug) or during early boot (auto)
+ The hotplug mode is the recommended default on all systems but container guests.
+ The auto mode can fail if the adapter is not initializing fast enough.
+ --client|--hotspot WiFi client or hotspot mode, which defaults to client for new interfaces
+ --ssid WiFi hotspot SSID
+ --key WiFi hotspot WPA passphrase
+ --freq 2.4|5 WiFi hotspot frequency band
+ --channel WiFi hotspot channel for the selected frequency band
+ --wifi4 0|1 Enable or disable WiFi 4 / 802.11n support for hotspot mode
+ --wifi5 0|1 Enable or disable WiFi 5 / 802.11ac support for hotspot mode
+ --wifi6 0|1 Enable or disable WiFi 6 / 802.11ax support for hotspot mode
+ --no-restart Write config only, do not reconnect the interface now
+ --force Proceed even if a network conflict (same subnet/duplicate default route) with
+ another enabled interface is detected, or if the interface does not exist at all.
+'
+
+. /boot/dietpi/func/dietpi-globals
+readonly G_PROGRAM_NAME='dietpi-network'
+G_CHECK_ROOT_USER "$@"
+G_CHECK_ROOTFS_RW
+G_INIT
+
+COMMAND='menu'
+ENTRY_MENU='main'
+NEXT_MENU='main'
+MAIN_MENU_LASTITEM=
+IFACE_MENU_LASTITEM=
+PROXY_MENU_LASTITEM=
+PRESERVE_SELECTED_SETTINGS=0
+ACTION_VALUE=
+ACTION_EXTRA=
+APPLY_IFACE=
+APPLY_RESTART=1
+APPLY_FORCE=0
+APPLY_ENABLE=
+APPLY_MODE=
+APPLY_COPY_CURRENT=0
+APPLY_BOOT_MODE=
+APPLY_ROLE=
+APPLY_IP=
+APPLY_GATEWAY=
+APPLY_DNS=
+APPLY_SSID=
+APPLY_KEY=
+APPLY_FREQ=
+APPLY_CHANNEL=
+APPLY_WIFI4=
+APPLY_WIFI5=
+APPLY_WIFI6=
+CURRENT_IFACE=
+CURRENT_IFACE_TYPE=
+CURRENT_IFACE_ENABLED=0
+CURRENT_IFACE_REAL=0
+CURRENT_IFACE_CONNECTED=0
+CURRENT_IFACE_MODE='dhcp'
+CURRENT_IFACE_IP_STATIC=
+CURRENT_IFACE_GATEWAY_STATIC=
+CURRENT_IFACE_DNS_STATIC=
+(( $G_HW_MODEL == 75 )) && CURRENT_IFACE_BOOT_MODE='auto' || CURRENT_IFACE_BOOT_MODE='allow-hotplug'
+CURRENT_IFACE_IP='0.0.0.0/24'
+CURRENT_IFACE_GATEWAY='0.0.0.0'
+CURRENT_IFACE_SOURCE=
+CURRENT_IFACE_HOTSPOT=0
+CURRENT_IFACE_HOTSPOT_ACTIVE=0
+CURRENT_IFACE_WIFI_SSID='Disconnected / No SSID'
+CURRENT_IFACE_WIFI_BITRATE=0
+CURRENT_IFACE_WIFI_SIGNAL='N/A'
+CURRENT_IFACE_WIFI_AUTO_RECONNECT=0
+CURRENT_WIFI_COUNTRYCODE='00'
+DNS_CURRENT='0.0.0.0'
+HOTSPOT_SSID=
+HOTSPOT_KEY=
+HOTSPOT_CHANNEL=
+HOTSPOT_WIFI4=0
+HOTSPOT_WIFI5=0
+HOTSPOT_WIFI6=0
+HOTSPOT_5G=0
+HOTSPOT_5G_CHANNEL=
+INTERNET_TEST_STATE=0
+INTERNET_TEST_URL='https://dietpi.com/'
+NET_RX_BYTE=0
+NET_TX_BYTE=0
+NET_RX_MB='N/A'
+NET_TX_MB='N/A'
+PROXY_ENABLED=0
+PROXY_ADDRESS=
+PROXY_PORT=
+PROXY_USERNAME=
+PROXY_PASSWORD=
+ETH_INTERFACES=()
+WIFI_INTERFACES=()
+
+Error(){ G_DIETPI-NOTIFY 1 "$1"; exit 1; }
+
+CIDR_From_Mask()
+{
+ local octet bits=0
+ IFS=. read -ra octet <<< "$1"
+ for octet in "${octet[@]}"
+ do
+ while (( $octet ))
+ do
+ ((bits+=octet&1)) # add last bit from octet to $bits
+ ((octet>>=1)) # remove last bit from octet
+ done
+ done
+ echo "$bits"
+}
+
+Get_Default_DNS()
+{
+ local dns=$(mawk '$1=="nameserver"{print $2}' ORS=' ' /etc/resolv.conf 2> /dev/null)
+ dns=${dns% }
+ echo "${dns:-9.9.9.9 149.112.112.112}" # default to Quad9 DNS
+}
+
+Get_Interfaces()
+{
+ ETH_INTERFACES=()
+ WIFI_INTERFACES=()
+ local iface
+ for iface in /sys/class/net/*
+ do
+ [[ $iface != *'/lo' && -d $iface ]] || continue
+ iface=${iface##*/}
+ Interface_Is_Real "$iface" || continue
+ if Interface_Is_Wifi
+ then
+ WIFI_INTERFACES+=("$iface")
+ else
+ ETH_INTERFACES+=("$iface")
+ fi
+ done
+}
+
+Interface_Is_Wifi(){ [[ $1 == 'wlan'[0-9]* || -d /sys/class/net/$1/wireless ]]; }
+# Excludes bridges/bonds/tunnels and other non-Ethernet devices, but keeps veth-based container interfaces (e.g. LXC "host0"), which lack a backing /sys/class/net//device path but are still real, configurable network interfaces.
+Interface_Is_Real()
+{
+ local type
+ read -r type < "/sys/class/net/$1/type" 2> /dev/null
+ [[ $type == 1 ]] || return 1
+
+ [[ -d /sys/class/net/$1/bridge || -d /sys/class/net/$1/bonding || -e /sys/class/net/$1/tun_flags ]] && return 1
+
+ return 0
+}
+Wifi_Modules_Enabled(){ [[ ! -f '/etc/modprobe.d/dietpi-disable_wifi.conf' ]]; }
+Onboard_Wifi_Enabled(){ [[ ! -f '/boot/firmware/config.txt' ]] || ! grep -q '^[[:blank:]]*dtoverlay=disable-wifi' /boot/firmware/config.txt; }
+Onboard_Wifi_Text(){ Onboard_Wifi_Enabled && echo 'On' || echo 'Off'; }
+Current_Interface_Type_Text(){ [[ $CURRENT_IFACE_TYPE == 'wifi' ]] && echo 'WiFi' || echo 'Ethernet'; }
+
+Net_Update_UsageStats()
+{
+ NET_RX_BYTE=0
+ NET_TX_BYTE=0
+ NET_RX_MB='N/A'
+ NET_TX_MB='N/A'
+ [[ -f /sys/class/net/$1/statistics/rx_bytes && -f /sys/class/net/$1/statistics/tx_bytes ]] || return 1
+ read -r NET_RX_BYTE < "/sys/class/net/$1/statistics/rx_bytes"
+ disable_error=1 G_CHECK_VALIDINT "$NET_RX_BYTE" 1 && NET_RX_MB="$(( $NET_RX_BYTE / 1024**2 )) MiB"
+ read -r NET_TX_BYTE < "/sys/class/net/$1/statistics/tx_bytes"
+ disable_error=1 G_CHECK_VALIDINT "$NET_TX_BYTE" 1 && NET_TX_MB="$(( $NET_TX_BYTE / 1024**2 )) MiB"
+}
+
+Load_Proxy_Vars()
+{
+ [[ $http_proxy ]] || http_proxy=
+ if [[ -f '/etc/bashrc.d/dietpi-proxy.sh' ]]
+ then
+ PROXY_ENABLED=1
+ # shellcheck disable=SC1091
+ . /etc/bashrc.d/dietpi-proxy.sh
+ else
+ PROXY_ENABLED=0
+ fi
+
+ if [[ $http_proxy ]]
+ then
+ PROXY_ADDRESS=${http_proxy#*//}; PROXY_ADDRESS=${PROXY_ADDRESS%:*}
+ PROXY_PORT=${http_proxy##*:}
+ if [[ $http_proxy == *'@'* ]]
+ then
+ PROXY_ADDRESS=${PROXY_ADDRESS#*@}
+ PROXY_USERNAME=${http_proxy#*//}; PROXY_USERNAME=${PROXY_USERNAME%%:*}
+ PROXY_PASSWORD=${http_proxy%%@*}; PROXY_PASSWORD=${PROXY_PASSWORD##*:}
+ fi
+ else
+ PROXY_ADDRESS=$(sed -n '/^[[:blank:]]*CONFIG_PROXY_ADDRESS=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
+ PROXY_PORT=$(sed -n '/^[[:blank:]]*CONFIG_PROXY_PORT=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
+ PROXY_USERNAME=$(sed -n '/^[[:blank:]]*CONFIG_PROXY_USERNAME=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
+ PROXY_PASSWORD=$(sed -n '/^[[:blank:]]*CONFIG_PROXY_PASSWORD=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
+ fi
+}
+
+Apply_Proxy_Settings()
+{
+ G_CONFIG_INJECT 'CONFIG_PROXY_ADDRESS=' "CONFIG_PROXY_ADDRESS=$PROXY_ADDRESS" /boot/dietpi.txt
+ G_CONFIG_INJECT 'CONFIG_PROXY_PORT=' "CONFIG_PROXY_PORT=$PROXY_PORT" /boot/dietpi.txt
+ G_CONFIG_INJECT 'CONFIG_PROXY_USERNAME=' "CONFIG_PROXY_USERNAME=$PROXY_USERNAME" /boot/dietpi.txt
+ GCI_PASSWORD=1 G_CONFIG_INJECT 'CONFIG_PROXY_PASSWORD=' "CONFIG_PROXY_PASSWORD=$PROXY_PASSWORD" /boot/dietpi.txt
+
+ if (( $PROXY_ENABLED ))
+ then
+ if [[ $PROXY_USERNAME && $PROXY_PASSWORD ]]
+ then
+ echo "export {http,https,ftp}_proxy='http://$PROXY_USERNAME:$PROXY_PASSWORD@$PROXY_ADDRESS:$PROXY_PORT'" > /etc/bashrc.d/dietpi-proxy.sh || exit 1
+ else
+ echo "export {http,https,ftp}_proxy='http://$PROXY_ADDRESS:$PROXY_PORT'" > /etc/bashrc.d/dietpi-proxy.sh || exit 1
+ fi
+ else
+ [[ -f '/etc/bashrc.d/dietpi-proxy.sh' ]] && G_EXEC rm /etc/bashrc.d/dietpi-proxy.sh
+ unset -v {http,https,ftp}_proxy # Has no effect on current login session but for this script, e.g. connection test
+ fi
+}
+
+Parse_Interface_Config()
+{
+ local file=$1 iface=$2 data
+ [[ -f $file ]] || return 1
+ data=$(mawk -v iface="$iface" '
+ BEGIN{OFS="\034"}
+ {
+ if (inblock && $1~/^(iface|auto|allow-auto|allow-hotplug|mapping|source)$/) inblock=0
+ if ($1~/^(auto|allow-auto|allow-hotplug)$/ && $2==iface) {found=1; enabled=1; bootmode=$1; next}
+ if ($1=="iface" && $2==iface) {inblock=1; found=1; mode=$4; next}
+ if (!inblock) next
+ if ($1=="address") address=$2
+ else if ($1=="netmask") netmask=$2
+ else if ($1=="gateway") gateway=$2
+ else if ($1=="dns-nameservers") {dns=""; for(i=2;i<=NF;i++) dns=dns (dns?" ":"") $i}
+ else if ($0=="up iptables-restore < /etc/iptables.ipv4.nat") hotspot=1
+ }
+ END{print found,enabled,bootmode,mode,address,netmask,gateway,dns,hotspot}
+ ' "$file") || return 1
+ IFS=$'\034' read -r PARSE_FOUND PARSE_ENABLED PARSE_BOOT_MODE PARSE_MODE PARSE_ADDRESS PARSE_NETMASK PARSE_GATEWAY PARSE_DNS PARSE_HOTSPOT <<< "$data"
+ (( $PARSE_FOUND )) || return 1
+ return 0
+}
+
+Get_Interface_Stored_Settings()
+{
+ local iface=$1
+ CURRENT_IFACE_SOURCE=
+ CURRENT_IFACE_ENABLED=0
+ (( $G_HW_MODEL == 75 )) && CURRENT_IFACE_BOOT_MODE='auto' || CURRENT_IFACE_BOOT_MODE='allow-hotplug'
+ CURRENT_IFACE_MODE='dhcp'
+ CURRENT_IFACE_IP_STATIC='192.168.0.100/24'
+ CURRENT_IFACE_GATEWAY_STATIC='192.168.0.1'
+ CURRENT_IFACE_DNS_STATIC=$(Get_Default_DNS)
+ CURRENT_IFACE_HOTSPOT=0
+
+ if Parse_Interface_Config "/etc/network/interfaces.d/$iface.conf" "$iface"
+ then
+ CURRENT_IFACE_SOURCE="/etc/network/interfaces.d/$iface.conf"
+
+ elif Parse_Interface_Config '/etc/network/interfaces' "$iface"
+ then
+ CURRENT_IFACE_SOURCE='/etc/network/interfaces'
+ else
+ return 0
+ fi
+
+ CURRENT_IFACE_ENABLED=${PARSE_ENABLED:-0}
+ [[ $PARSE_BOOT_MODE ]] && CURRENT_IFACE_BOOT_MODE=$PARSE_BOOT_MODE
+ [[ $PARSE_MODE == 'static' ]] && CURRENT_IFACE_MODE='static'
+ if [[ $PARSE_ADDRESS ]]
+ then
+ CURRENT_IFACE_IP_STATIC=$PARSE_ADDRESS
+ [[ $CURRENT_IFACE_IP_STATIC == */* ]] || CURRENT_IFACE_IP_STATIC+="/$(CIDR_From_Mask "${PARSE_NETMASK:-255.255.255.0}")"
+ fi
+ [[ $PARSE_GATEWAY ]] && CURRENT_IFACE_GATEWAY_STATIC=$PARSE_GATEWAY
+ [[ $PARSE_DNS ]] && CURRENT_IFACE_DNS_STATIC=$PARSE_DNS
+ CURRENT_IFACE_HOTSPOT=${PARSE_HOTSPOT:-0}
+}
+
+Load_Hotspot_Settings()
+{
+ if [[ -f '/etc/hostapd/hostapd.conf' ]]
+ then
+ HOTSPOT_SSID=$(sed -n '/^[[:blank:]]*ssid=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)
+ HOTSPOT_KEY=$(sed -n '/^[[:blank:]]*wpa_passphrase=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)
+ HOTSPOT_WIFI4=$(grep -cm1 '^[[:blank:]]*ieee80211n=1$' /etc/hostapd/hostapd.conf)
+ HOTSPOT_WIFI5=$(grep -cm1 '^[[:blank:]]*ieee80211ac=1$' /etc/hostapd/hostapd.conf)
+ HOTSPOT_WIFI6=$(grep -cm1 '^[[:blank:]]*ieee80211ax=1$' /etc/hostapd/hostapd.conf)
+ HOTSPOT_5G=$(grep -cm1 '^[[:blank:]]*hw_mode=a$' /etc/hostapd/hostapd.conf)
+ HOTSPOT_5G_CHANNEL=$(sed -n '/^[[:blank:]]*channel=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)
+ HOTSPOT_CHANNEL=$(sed -n '/^[[:blank:]]*channel=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)
+ fi
+ if (( $HOTSPOT_5G ))
+ then
+ [[ $HOTSPOT_5G_CHANNEL ]] || HOTSPOT_5G_CHANNEL=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_5G_CHANNEL=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
+ [[ $HOTSPOT_5G_CHANNEL ]] || HOTSPOT_5G_CHANNEL=36
+ else
+ [[ $HOTSPOT_CHANNEL ]] || HOTSPOT_CHANNEL=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_CHANNEL=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
+ [[ $HOTSPOT_CHANNEL ]] || HOTSPOT_CHANNEL=3
+ fi
+ [[ $HOTSPOT_SSID ]] || HOTSPOT_SSID='DietPi-Hotspot'
+ [[ $HOTSPOT_KEY ]] || HOTSPOT_KEY='dietpihotspot'
+}
+
+Load_Interface_State()
+{
+ local iface=$1
+ CURRENT_IFACE=$iface
+ Interface_Is_Real "$iface" && CURRENT_IFACE_REAL=1 || CURRENT_IFACE_REAL=0
+ Interface_Is_Wifi "$iface" && CURRENT_IFACE_TYPE='wifi' || CURRENT_IFACE_TYPE='eth'
+ CURRENT_IFACE_CONNECTED=0
+ CURRENT_IFACE_IP='0.0.0.0/24'
+ CURRENT_IFACE_GATEWAY='0.0.0.0'
+ CURRENT_IFACE_WIFI_SSID='Disconnected / No SSID'
+ CURRENT_IFACE_WIFI_BITRATE=0
+ CURRENT_IFACE_WIFI_SIGNAL='N/A'
+ CURRENT_IFACE_WIFI_AUTO_RECONNECT=0
+ CURRENT_IFACE_HOTSPOT=0
+ CURRENT_IFACE_HOTSPOT_ACTIVE=0
+ DNS_CURRENT=$(Get_Default_DNS)
+ (( $PRESERVE_SELECTED_SETTINGS )) || Get_Interface_Stored_Settings "$iface"
+
+ if (( $CURRENT_IFACE_REAL ))
+ then
+ CURRENT_IFACE_CONNECTED=$(ip -o r l dev "$iface" 2> /dev/null | grep -vcm1 '[[:blank:]]linkdown')
+ if (( $CURRENT_IFACE_CONNECTED ))
+ then
+ CURRENT_IFACE_IP=$(ip -br -f inet a s "$iface" 2> /dev/null | mawk '{print $3}')
+ CURRENT_IFACE_GATEWAY=$(ip r l dev "$iface" 0/0 2> /dev/null | mawk '{print $3;exit}')
+ fi
+ fi
+
+ if [[ $CURRENT_IFACE_TYPE == 'wifi' ]]
+ then
+ # Only the WiFi interface referenced by hostapd can expose the single global hotspot configuration.
+ [[ -f '/etc/hostapd/hostapd.conf' ]] && grep -q "^[[:blank:]]*interface=$iface$" /etc/hostapd/hostapd.conf && CURRENT_IFACE_HOTSPOT=1
+ if (( $CURRENT_IFACE_CONNECTED ))
+ then
+ CURRENT_IFACE_WIFI_SSID=$(iw dev "$iface" link 2> /dev/null | mawk '$1=="SSID:"{print $2;exit}')
+ [[ $CURRENT_IFACE_WIFI_SSID ]] || CURRENT_IFACE_WIFI_SSID='Disconnected / No SSID'
+ CURRENT_IFACE_WIFI_BITRATE=$(iw dev "$iface" link 2> /dev/null | mawk '$1$2=="txbitrate:"{print $3;exit}')
+ [[ $CURRENT_IFACE_WIFI_BITRATE ]] || CURRENT_IFACE_WIFI_BITRATE=0
+ local signal=$(iw dev "$iface" link 2> /dev/null | mawk '$1=="signal:"{print $2;exit}')
+ if disable_error=1 G_CHECK_VALIDINT "$signal" -500 -1
+ then
+ CURRENT_IFACE_WIFI_SIGNAL="$signal dBm"
+
+ elif [[ $signal ]]
+ then
+ CURRENT_IFACE_WIFI_SIGNAL="$signal %"
+ fi
+ fi
+ systemctl -q is-active dietpi-wifi-monitor && CURRENT_IFACE_WIFI_AUTO_RECONNECT=1 || CURRENT_IFACE_WIFI_AUTO_RECONNECT=0
+ if (( $CURRENT_IFACE_HOTSPOT ))
+ then
+ Load_Hotspot_Settings
+ systemctl -q is-active hostapd && CURRENT_IFACE_HOTSPOT_ACTIVE=1 || CURRENT_IFACE_HOTSPOT_ACTIVE=0
+ CURRENT_WIFI_COUNTRYCODE=$(sed -n '/^[[:blank:]]*country_code=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)
+
+ elif [[ -f '/etc/wpa_supplicant/wpa_supplicant.conf' ]]
+ then
+ CURRENT_WIFI_COUNTRYCODE=$(sed -n '/^[[:blank:]]*country=/{s/^[^=]*=//p;q}' /etc/wpa_supplicant/wpa_supplicant.conf)
+ fi
+ [[ $CURRENT_WIFI_COUNTRYCODE ]] || CURRENT_WIFI_COUNTRYCODE=$(iw reg get 2> /dev/null | mawk -F'[ :]' '/country/{print $2;exit}')
+ [[ $CURRENT_WIFI_COUNTRYCODE ]] || CURRENT_WIFI_COUNTRYCODE='00'
+ else
+ # Ethernet cannot be a hotspot
+ CURRENT_IFACE_HOTSPOT=0
+ fi
+}
+
+Remove_Interface_From_Main_File()
+{
+ local iface=$1 config='/etc/network/interfaces' tmp
+ [[ $iface && -f $config ]] || return 0
+ tmp=$(mktemp) || exit 1
+ mawk -v iface="$iface" '
+ function top(line){return line ~ /^[[:blank:]]*(iface|auto|allow-hotplug|mapping|source)([[:blank:]]|$)/}
+ {
+ if (skip)
+ {
+ if (top($0)) skip=0
+ else next
+ }
+ if ($0 ~ "^[[:blank:]]*#?[[:blank:]]*(allow-hotplug|auto)[[:blank:]]+" iface "([[:blank:]]|$)") next
+ if ($0 ~ "^[[:blank:]]*iface[[:blank:]]+" iface "([[:blank:]]|$)") {skip=1; next}
+ print
+ }
+ ' "$config" > "$tmp" && G_EXEC_NOEXIT=1 G_EXEC mv "$tmp" "$config"
+ [[ -f $tmp ]] && G_EXEC rm "$tmp"
+}
+
+Update_ResolvConf_Fallback()
+{
+ (( $CURRENT_IFACE_ENABLED )) || return 0
+ [[ $CURRENT_IFACE_MODE == 'static' ]] || return 0
+ [[ $CURRENT_IFACE_DNS_STATIC ]] || return 0
+ command -v resolvconf > /dev/null && return 0
+ > /etc/resolv.conf
+ local server
+ for server in $CURRENT_IFACE_DNS_STATIC
+ do
+ echo "nameserver $server" >> /etc/resolv.conf
+ done
+}
+
+Write_Interface_Config()
+{
+ local iface=$CURRENT_IFACE
+ local fp="/etc/network/interfaces.d/$iface.conf"
+ local gateway_line dns_line
+
+ # WiFi Hotspot requires a static IP, but must not have a gateway or DNS
+ if (( $CURRENT_IFACE_HOTSPOT ))
+ then
+ CURRENT_IFACE_MODE='static'
+
+ elif [[ $CURRENT_IFACE_MODE == 'static' ]]
+ then
+ [[ $CURRENT_IFACE_GATEWAY_STATIC ]] && gateway_line="gateway $CURRENT_IFACE_GATEWAY_STATIC"
+ [[ $CURRENT_IFACE_DNS_STATIC ]] && command -v resolvconf > /dev/null && dns_line="dns-nameservers $CURRENT_IFACE_DNS_STATIC"
+ fi
+
+ # Header
+ local content="# Location: $fp"$'\n''# Generated with: dietpi-network'
+ (( $CURRENT_IFACE_ENABLED )) && content+=$'\n'"$CURRENT_IFACE_BOOT_MODE $iface"
+ content+=$'\n'"iface $iface inet $CURRENT_IFACE_MODE"
+
+ # Static IP
+ if [[ $CURRENT_IFACE_MODE == 'static' ]]
+ then
+ content+=$'\n'"address $CURRENT_IFACE_IP_STATIC"
+ [[ $gateway_line ]] && content+=$'\n'"$gateway_line"
+ [[ $dns_line ]] && content+=$'\n'"$dns_line"
+ fi
+
+ # WiFi
+ if [[ $CURRENT_IFACE_TYPE == 'wifi' ]]
+ then
+ content+=$'\n''wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf'
+
+ # Disable power savings mode if supported
+ if iw dev "$iface" set power_save on 2> /dev/null && iw dev "$iface" set power_save off 2> /dev/null
+ then
+ content+=$'\n'"pre-up iw dev $iface set power_save off || true"
+ content+=$'\n'"post-down iw dev $iface set power_save on || true"
+ fi
+
+ # WiFi Hotspot
+ if (( $CURRENT_IFACE_HOTSPOT ))
+ then
+ content+=$'\n''up iptables-restore < /etc/iptables.ipv4.nat'
+ content+=$'\n''up ip6tables-restore < /etc/iptables.ipv6.nat'
+ [[ -f '/etc/hostapd/hostapd.conf' ]] && G_CONFIG_INJECT 'interface=' "interface=$iface" /etc/hostapd/hostapd.conf
+ [[ -f '/etc/default/isc-dhcp-server' ]] && G_CONFIG_INJECT 'INTERFACESv4=' "INTERFACESv4=\"$iface\"" /etc/default/isc-dhcp-server
+ fi
+ fi
+
+ # Write config
+ [[ -f '/etc/network/interfaces.d' ]] || G_EXEC mkdir -p /etc/network/interfaces.d
+ echo "$content" > "$fp" || exit 1
+ grep -q '^source interfaces\.d/\*$' /etc/network/interfaces || G_CONFIG_INJECT 'source interfaces.d/' 'source interfaces.d/*' /etc/network/interfaces
+
+ Remove_Interface_From_Main_File "$iface"
+ Update_ResolvConf_Fallback
+}
+
+Restart_Interface()
+{
+ local iface=$1
+
+ # WiFi Hotspot: Stop DHCP server and hostapd before restarting interface
+ (( $CURRENT_IFACE_HOTSPOT )) && G_EXEC systemctl stop isc-dhcp-server hostapd
+
+ G_DIETPI-NOTIFY 2 "Restarting $iface, please wait ..."
+
+ # Only try to configure if this is Ethernet, a hotspot, or an SSID has been configured
+ if (( $CURRENT_IFACE_ENABLED )) && { [[ $CURRENT_IFACE_TYPE != 'wifi' || $CURRENT_IFACE_HOTSPOT == 1 ]] || grep -q '^network=' /etc/wpa_supplicant/wpa_supplicant.conf 2> /dev/null; }
+ then
+ if [[ $CURRENT_IFACE_BOOT_MODE == 'allow-hotplug' ]]
+ then
+ if (( $G_DISTRO > 8 ))
+ then
+ # From Forky on, there is a -v flag to print journalctl output for this unit during operation.
+ G_EXEC_NOHALT=1 G_EXEC_OUTPUT=1 G_EXEC systemctl -v restart "ifup@$iface"
+ else
+ # Else, archive the same with a journalctl -f call as background job
+ journalctl -fn 0 -u "ifup@$iface" &
+ G_EXEC_NOHALT=1 G_EXEC_OUTPUT=1 G_EXEC systemctl restart "ifup@$iface"
+ kill -15 %%
+ fi
+ else
+ G_EXEC_NOHALT=1 G_EXEC_OUTPUT=1 G_EXEC ifdown --force "$iface"
+ G_EXEC_NOHALT=1 G_EXEC_OUTPUT=1 G_EXEC ifup "$iface"
+ fi
+ else
+ ifdown --force "$iface" 2> /dev/null
+ fi
+
+ # WiFi Hotspot: Restart DHCP server and hostapd
+ (( $CURRENT_IFACE_HOTSPOT )) && G_EXEC systemctl start hostapd isc-dhcp-server
+
+ G_SLEEP 2 # for the state to settle
+ G_DIETPI-NOTIFY 0 "$iface restarted"
+}
+
+Copy_Current_To_Static()
+{
+ (( $CURRENT_IFACE_CONNECTED )) || return 0
+ CURRENT_IFACE_IP_STATIC=$CURRENT_IFACE_IP
+ CURRENT_IFACE_GATEWAY_STATIC=$CURRENT_IFACE_GATEWAY
+ CURRENT_IFACE_DNS_STATIC=$DNS_CURRENT
+}
+
+Change_StaticIp()
+{
+ G_WHIP_INPUTBOX_REGEX='^([0-9]{1,3}\.){3}[0-9]{1,3}(/[0-9]+)?$'
+ G_WHIP_INPUTBOX_REGEX_TEXT='be a valid IPv4 address with optional netmask CIDR notation, e.g. "192.168.0.100" or "192.168.0.100/24"'
+ G_WHIP_DEFAULT_ITEM=$CURRENT_IFACE_IP_STATIC
+ G_WHIP_INPUTBOX "Please enter a new static $(Current_Interface_Type_Text) IP address, optionally in CIDR notation to define a subnet mask other than the default /24 (255.255.255.0), e.g.: 192.168.0.100/24" || return 0
+ CURRENT_IFACE_IP_STATIC=$G_WHIP_RETURNED_VALUE
+ [[ $CURRENT_IFACE_IP_STATIC == */* ]] || CURRENT_IFACE_IP_STATIC+='/24'
+}
+
+Change_StaticGateway()
+{
+ G_WHIP_INPUTBOX_REGEX='^(([0-9]{1,3}\.){3}[0-9]{1,3})?$'
+ G_WHIP_INPUTBOX_REGEX_TEXT='be a valid IPv4 address, e.g. "192.168.0.1", or empty'
+ G_WHIP_DEFAULT_ITEM=${CURRENT_IFACE_GATEWAY_STATIC:-${CURRENT_IFACE_IP_STATIC%.*}.1}
+ G_WHIP_INPUTBOX "Please enter a new static $(Current_Interface_Type_Text) gateway address. You can leave this empty if this interface shall not be used for Internet access." || return 0
+ CURRENT_IFACE_GATEWAY_STATIC=$G_WHIP_RETURNED_VALUE
+}
+
+Change_StaticDns()
+{
+ G_WHIP_DEFAULT_ITEM=$CURRENT_IFACE_DNS_STATIC
+ G_WHIP_MENU_ARRAY=("$CURRENT_IFACE_DNS_STATIC" ': Your current DNS server')
+ local gateway=$(G_GET_NET -q gateway)
+ [[ $gateway ]] && G_WHIP_MENU_ARRAY+=("$gateway" ': Use local router as DNS server (recommended)')
+ ss -uln 2> /dev/null | grep -q ':53[[:blank:]]' && G_WHIP_MENU_ARRAY+=('127.0.0.1' ': Use local Pi-hole/AdGuard Home/Unbound')
+ G_WHIP_MENU_ARRAY+=(
+ 'Custom' ': Manually enter your DNS server'
+ '' '●─ Public DNS providers '
+ '1.1.1.1 1.0.0.1' ': Cloudflare'
+ '9.9.9.9 149.112.112.112' ': Quad9'
+ '8.8.8.8 8.8.4.4' ': Google'
+ '208.67.222.222 208.67.220.220' ': OpenDNS'
+ '209.244.0.3 209.244.0.4' ': Level3'
+ '216.146.35.35 216.146.36.36' ': Dyn'
+ '37.235.1.174 37.235.1.177' ': FreeDNS'
+ '64.6.64.6 64.6.65.6' ': Verisign'
+ '84.200.69.80 84.200.70.40' ': DNS.WATCH'
+ )
+ G_WHIP_MENU 'Please select a DNS server, or choose "Custom" for manual entry:' || return 0
+ if [[ $G_WHIP_RETURNED_VALUE == 'Custom' ]]
+ then
+ G_WHIP_INPUTBOX_REGEX='^([0-9]{1,3}\.){3}[0-9]{1,3}( ([0-9]{1,3}\.){3}[0-9]{1,3})?$'
+ G_WHIP_INPUTBOX_REGEX_TEXT='be one or two space-separated valid IPv4 address, e.g. "9.9.9.9" or "9.9.9.9 149.112.112.112"'
+ G_WHIP_DEFAULT_ITEM=$CURRENT_IFACE_DNS_STATIC
+ G_WHIP_INPUTBOX "Please enter one or two space-separated DNS server addresses.
+ - E.g.: 9.9.9.9 149.112.112.112
+ - Current: $CURRENT_IFACE_DNS_STATIC" || return 0
+ fi
+ CURRENT_IFACE_DNS_STATIC=$G_WHIP_RETURNED_VALUE
+}
+
+Change_WifiCountryCode()
+{
+ G_WHIP_MENU_ARRAY=(
+ 'GB' ': Great Britain'
+ 'DE' ': Germany'
+ 'US' ': United States'
+ 'JP' ': Japan'
+ 'CN' ': China'
+ 'IN' ': India'
+ 'Manual' ': Enter a custom country code'
+ )
+ G_WHIP_DEFAULT_ITEM=$CURRENT_WIFI_COUNTRYCODE
+ G_WHIP_BUTTON_CANCEL_TEXT='Cancel'
+ G_WHIP_MENU 'Please select your country to enable WiFi channels and power ratings allowed in your region.
+\nNB: Verify the active code with:\n# iw reg get' || return 0
+ if [[ $G_WHIP_RETURNED_VALUE == 'Manual' ]]
+ then
+ G_WHIP_INPUTBOX_REGEX='^[[:upper:]][[:upper:]]$'
+ G_WHIP_INPUTBOX_REGEX_TEXT='a 2 capital letter country code'
+ G_WHIP_DEFAULT_ITEM=$CURRENT_WIFI_COUNTRYCODE
+ G_WHIP_INPUTBOX 'Please enter a 2 capital letter country code: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2' || return 0
+ fi
+ CURRENT_WIFI_COUNTRYCODE=$G_WHIP_RETURNED_VALUE
+ /boot/dietpi/func/dietpi-set_hardware wificountrycode "$CURRENT_WIFI_COUNTRYCODE"
+}
+
+Change_BootMode()
+{
+ G_WHIP_MENU_ARRAY=(
+ 'Hotplug' ': Bring up interface once adapter is detected/plugged'
+ 'Auto' ': Bring up interface during early boot'
+ )
+ G_WHIP_DEFAULT_ITEM=${CURRENT_IFACE_BOOT_MODE#allow-}
+ G_WHIP_MENU 'Please select how the interface should be brought up at boot.
+\nNB: The auto mode can fail if the adapter is not initializing fast enough. And it won'\''t bring the interface back up automatically, when the adapter is physically detected and re-attached. We hence recommend the hotplug mode.
+Only exception are container guest systems, where the hotplug mode cannot usually work, as it is triggered by udev events about added (detected) network adapters.' || return 0
+ [[ $G_WHIP_RETURNED_VALUE == 'Auto' ]] && CURRENT_IFACE_BOOT_MODE='auto' || CURRENT_IFACE_BOOT_MODE='allow-hotplug'
+}
+
+Apply_Hotspot_Settings()
+{
+ G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_SSID=' "SOFTWARE_WIFI_HOTSPOT_SSID=$HOTSPOT_SSID" /boot/dietpi.txt
+ GCI_PASSWORD=1 G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_KEY=' "SOFTWARE_WIFI_HOTSPOT_KEY=$HOTSPOT_KEY" /boot/dietpi.txt
+ G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_CHANNEL=' "SOFTWARE_WIFI_HOTSPOT_CHANNEL=$HOTSPOT_CHANNEL" /boot/dietpi.txt
+ G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_WIFI4=' "SOFTWARE_WIFI_HOTSPOT_WIFI4=$HOTSPOT_WIFI4" /boot/dietpi.txt
+ G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_WIFI5=' "SOFTWARE_WIFI_HOTSPOT_WIFI5=$HOTSPOT_WIFI5" /boot/dietpi.txt
+ G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_WIFI6=' "SOFTWARE_WIFI_HOTSPOT_WIFI6=$HOTSPOT_WIFI6" /boot/dietpi.txt
+ G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_5G=' "SOFTWARE_WIFI_HOTSPOT_5G=$HOTSPOT_5G" /boot/dietpi.txt
+ G_CONFIG_INJECT 'SOFTWARE_WIFI_HOTSPOT_5G_CHANNEL=' "SOFTWARE_WIFI_HOTSPOT_5G_CHANNEL=$HOTSPOT_5G_CHANNEL" /boot/dietpi.txt
+ [[ -f '/etc/hostapd/hostapd.conf' ]] || { G_WHIP_MSG '[FAILED] /etc/hostapd/hostapd.conf does not exist, cannot apply WiFi hotspot settings'; return 1; }
+ G_CONFIG_INJECT 'ssid=' "ssid=$HOTSPOT_SSID" /etc/hostapd/hostapd.conf
+ G_CONFIG_INJECT 'wpa_passphrase=' "wpa_passphrase=$HOTSPOT_KEY" /etc/hostapd/hostapd.conf
+ G_CONFIG_INJECT 'ieee80211n=' "ieee80211n=$HOTSPOT_WIFI4" /etc/hostapd/hostapd.conf
+ G_CONFIG_INJECT 'ieee80211ac=' "ieee80211ac=$HOTSPOT_WIFI5" /etc/hostapd/hostapd.conf
+ G_CONFIG_INJECT 'ieee80211ax=' "ieee80211ax=$HOTSPOT_WIFI6" /etc/hostapd/hostapd.conf '^ieee80211ac'
+ if (( $HOTSPOT_WIFI4 || $HOTSPOT_WIFI5 || $HOTSPOT_WIFI6 ))
+ then
+ G_CONFIG_INJECT 'wmm_enabled=' 'wmm_enabled=1' /etc/hostapd/hostapd.conf
+ else
+ G_CONFIG_INJECT 'wmm_enabled=' 'wmm_enabled=0' /etc/hostapd/hostapd.conf
+ fi
+ if (( $HOTSPOT_5G ))
+ then
+ G_CONFIG_INJECT 'hw_mode=' 'hw_mode=a' /etc/hostapd/hostapd.conf
+ G_CONFIG_INJECT 'channel=' "channel=$HOTSPOT_5G_CHANNEL" /etc/hostapd/hostapd.conf
+ else
+ G_CONFIG_INJECT 'hw_mode=' 'hw_mode=g' /etc/hostapd/hostapd.conf
+ G_CONFIG_INJECT 'channel=' "channel=$HOTSPOT_CHANNEL" /etc/hostapd/hostapd.conf
+ fi
+}
+
+IP_To_Int()
+{
+ local a b c d
+ IFS=. read -r a b c d <<< "$1"
+ echo $(( (a<<24) + (b<<16) + (c<<8) + d ))
+}
+
+Subnets_Overlap()
+{
+ local ip1=${1%/*} p1=${1#*/} ip2=${2%/*} p2=${2#*/}
+ [[ $1 == */* ]] || p1=32
+ [[ $2 == */* ]] || p2=32
+ local i1=$(IP_To_Int "$ip1") i2=$(IP_To_Int "$ip2") p=$(( p1 < p2 ? p1 : p2 ))
+ local mask=$(( p == 0 ? 0 : ( 0xFFFFFFFF << ( 32 - p ) ) & 0xFFFFFFFF ))
+ (( ( $i1 & $mask ) == ( $i2 & $mask ) ))
+}
+
+# Determine the enabled state, mode, static/live subnet and gateway of another interface, without touching the CURRENT_IFACE_* state of the interface currently being configured.
+Get_Iface_Effective_Net()
+{
+ local iface=$1 enabled=0 mode='dhcp' cidr='' gateway=''
+ Parse_Interface_Config "/etc/network/interfaces.d/$iface.conf" "$iface" ||
+ Parse_Interface_Config '/etc/network/interfaces' "$iface" ||
+ PARSE_ENABLED=0 PARSE_MODE='dhcp' PARSE_ADDRESS='' PARSE_NETMASK='' PARSE_GATEWAY=''
+
+ enabled=${PARSE_ENABLED:-0}
+ [[ $PARSE_MODE == 'static' ]] && mode='static'
+ if [[ $mode == 'static' && $PARSE_ADDRESS ]]
+ then
+ cidr=$PARSE_ADDRESS
+ [[ $cidr == */* ]] || cidr+="/$(CIDR_From_Mask "${PARSE_NETMASK:-255.255.255.0}")"
+ fi
+ gateway=$PARSE_GATEWAY
+ if (( $enabled ))
+ then
+ local live=$(ip -br -f inet a s "$iface" 2> /dev/null | mawk '{print $3}')
+ [[ $live && ! $cidr ]] && cidr=$live
+ local live_gateway=$(ip r l dev "$iface" 0/0 2> /dev/null | mawk '{print $3;exit}')
+ [[ $live_gateway && ! $gateway ]] && gateway=$live_gateway
+ fi
+ echo "$enabled|$mode|$cidr|$gateway"
+}
+
+Disable_Conflicting_Interface()
+{
+ local iface=$1 fp
+ for fp in "/etc/network/interfaces.d/$iface.conf" '/etc/network/interfaces'
+ do
+ [[ -f $fp ]] || continue
+ G_EXEC_NOEXIT=1 G_EXEC sed --follow-symlinks -i "/^[[:blank:]]*\(allow-hotplug\|auto\)[[:blank:]]\+$iface\([[:blank:]]\|\$\)/s/^/#/" "$fp"
+ done
+ ifdown --force "$iface" 2> /dev/null
+ G_DIETPI-NOTIFY 2 "Disabled interface \"$iface\" to resolve network conflict"
+}
+
+# Avoid two enabled interfaces on the same subnet (asymmetric routing risk) or two default routes (DHCP usually assigns one, in addition to any configured static gateway)
+Check_Network_Conflicts()
+{
+ (( $APPLY_FORCE )) && return 0 # skip check if settings are to be applied anyway
+ (( $CURRENT_IFACE_ENABLED )) || return 0
+ [[ $CURRENT_IFACE_MODE == 'static' || $CURRENT_IFACE_MODE == 'dhcp' ]] || return 0
+ local iface o_enabled o_cidr o_gateway reason
+ for iface in /sys/class/net/*
+ do
+ [[ $iface != *'/lo' && -d $iface ]] || continue
+ iface=${iface##*/}
+ [[ $iface == "$CURRENT_IFACE" ]] && continue
+ # Only consider real Ethernet-like or WiFi adapters, same as Get_Interfaces()
+ Interface_Is_Real "$iface" || continue
+
+ IFS='|' read -r o_enabled _ o_cidr o_gateway < <(Get_Iface_Effective_Net "$iface")
+ (( $o_enabled )) || continue
+ if [[ $CURRENT_IFACE_MODE == 'static' && $CURRENT_IFACE_IP_STATIC && $o_cidr ]] && Subnets_Overlap "$CURRENT_IFACE_IP_STATIC" "$o_cidr"
+ then
+ reason="already uses the same subnet ($o_cidr) as the static IP address about to be assigned to \"$CURRENT_IFACE\" ($CURRENT_IFACE_IP_STATIC)"
+
+ elif [[ $CURRENT_IFACE_MODE == 'dhcp' && $o_gateway ]]
+ then
+ reason="already has a default gateway ($o_gateway) assigned, while \"$CURRENT_IFACE\" is about to be enabled with DHCP, which usually also assigns a default route"
+ else
+ continue
+ fi
+
+ G_WHIP_MENU_ARRAY=(
+ 'Ignore' ': Proceed and keep both interfaces enabled (NOT recommended)'
+ 'Disable' ": Disable \"$iface\" and proceed"
+ )
+ G_WHIP_MENU "[WARNING] Network conflict detected:\n\nInterface \"$iface\" $reason.\n\nHaving two enabled interfaces on the same subnet, or two default routes, can cause asymmetric traffic and break connectivity (e.g. to a connected SSH client).\n\nPlease select how to proceed:" || return 1
+ [[ $G_WHIP_RETURNED_VALUE == 'Disable' ]] && Disable_Conflicting_Interface "$iface"
+ done
+ return 0
+}
+
+Apply_Current_Interface()
+{
+ [[ $CURRENT_IFACE ]] || return 1
+ # Enable interface if it is not disabled via config or CLI option explicitly
+ [[ $CURRENT_IFACE_SOURCE == '/etc/network/interfaces.d/'* || $APPLY_ENABLE ]] || CURRENT_IFACE_ENABLED=1
+ if [[ $CURRENT_IFACE_TYPE == 'wifi' ]]
+ then
+ if (( $CURRENT_IFACE_HOTSPOT ))
+ then
+ (( ${#HOTSPOT_KEY} > 7 )) || { G_DIETPI-NOTIFY 1 'WiFi hotspot key must have at least 8 characters.'; return 1; }
+ Apply_Hotspot_Settings
+ else
+ (( $CURRENT_IFACE_ENABLED )) || G_EXEC_NOEXIT=1 G_EXEC systemctl disable --now dietpi-wifi-monitor
+ fi
+ fi
+ Check_Network_Conflicts || return 1
+ Write_Interface_Config
+ (( $1 )) && Restart_Interface "$CURRENT_IFACE"
+ PRESERVE_SELECTED_SETTINGS=0 # load settings in interface menu from config files again, now that we have written them
+}
+
+Interface_Menu_Title()
+{
+ local title
+ if [[ $CURRENT_IFACE_TYPE == 'wifi' ]]
+ then
+ if (( $CURRENT_IFACE_HOTSPOT ))
+ then
+ title="WiFi Hotspot: $CURRENT_IFACE"
+ else
+ title="WiFi Interface: $CURRENT_IFACE"
+ fi
+ else
+ title="Ethernet Interface: $CURRENT_IFACE"
+ fi
+ [[ $CURRENT_IFACE_SOURCE == '/etc/network/interfaces' ]] && title+=' (will be migrated from /etc/network/interfaces to its own drop-in on apply)'
+ echo "$title"
+}
+
+Return_From_Submenu(){ [[ $ENTRY_MENU == "$1" ]] && NEXT_MENU='exit' || NEXT_MENU='main'; }
+
+Interface_Status_Text()
+{
+ local iface=$1 type=$2 enabled='Off' mode='DHCP' connected='Disconnected'
+ CURRENT_IFACE=
+ Get_Interface_Stored_Settings "$iface"
+ (( $CURRENT_IFACE_ENABLED )) && enabled="On (${CURRENT_IFACE_BOOT_MODE#allow-})"
+ [[ $CURRENT_IFACE_MODE == 'static' ]] && mode='Static'
+ CURRENT_IFACE_CONNECTED=$(ip -o r l dev "$iface" 2> /dev/null | grep -vcm1 '[[:blank:]]linkdown')
+ (( $CURRENT_IFACE_CONNECTED )) && connected='Connected'
+ [[ $type == 'wifi' && -f '/etc/hostapd/hostapd.conf' ]] && grep -q "^[[:blank:]]*interface=$iface$" /etc/hostapd/hostapd.conf && connected='Hotspot'
+ echo "[$enabled] | $mode | $connected"
+}
+
+Menu_Main()
+{
+ Get_Interfaces
+ Load_Proxy_Vars
+ local wifi_modules_text='On' ipv6_enabled=1 ipv6_text='On' internet_text='Run internet connection test' proxy_state='[Off]' iface
+ Wifi_Modules_Enabled || wifi_modules_text='Off'
+ grep -q '^[[:blank:]]*CONFIG_ENABLE_IPV6=0' /boot/dietpi.txt && ipv6_enabled=0 ipv6_text='Off'
+ case $INTERNET_TEST_STATE in
+ 1) internet_text='[Failure] | Offline';;
+ 2) internet_text='[Success] | Online';;
+ *) :;;
+ esac
+ (( $PROXY_ENABLED )) && proxy_state="[On] | $PROXY_ADDRESS:$PROXY_PORT"
+
+ G_WHIP_MENU_ARRAY=()
+ if (( ${#ETH_INTERFACES[@]} ))
+ then
+ G_WHIP_MENU_ARRAY+=('' '●─ Ethernet Interfaces ')
+ for iface in "${ETH_INTERFACES[@]}"
+ do
+ G_WHIP_MENU_ARRAY+=("$iface" ": $(Interface_Status_Text "$iface" 'eth')")
+ done
+ fi
+ if (( ${#WIFI_INTERFACES[@]} ))
+ then
+ G_WHIP_MENU_ARRAY+=('' '●─ WiFi Interfaces ')
+ for iface in "${WIFI_INTERFACES[@]}"
+ do
+ G_WHIP_MENU_ARRAY+=("$iface" ": $(Interface_Status_Text "$iface" 'wifi')")
+ done
+ fi
+ G_WHIP_MENU_ARRAY+=(
+ '' '●─ Global Options '
+ 'WiFi modules' ": [$wifi_modules_text]"
+ )
+ (( ${G_HW_ONBOARD_WIFI:-0} )) && G_WHIP_MENU_ARRAY+=('Onboard WiFi' ": [$(Onboard_Wifi_Text)]")
+ [[ -d '/proc/sys/net/ipv6' ]] && G_WHIP_MENU_ARRAY+=('IPv6' ": [$ipv6_text]")
+ G_WHIP_MENU_ARRAY+=(
+ 'Proxy' ": $proxy_state"
+ 'Test' ": $internet_text"
+ )
+ G_WHIP_DEFAULT_ITEM=$MAIN_MENU_LASTITEM
+ G_WHIP_MENU "Hardware : $G_HW_MODEL_NAME" || { NEXT_MENU='exit'; return 0; }
+ MAIN_MENU_LASTITEM=$G_WHIP_RETURNED_VALUE
+ case $G_WHIP_RETURNED_VALUE in
+ 'WiFi modules')
+ if Wifi_Modules_Enabled
+ then
+ /boot/dietpi/func/dietpi-set_hardware wifimodules disable
+ [[ $(dpkg-query -s 'iw' 'wpasupplicant' 'wireless-regdb' 2> /dev/null) ]] || return 0
+ G_WHIP_BUTTON_CANCEL_TEXT='Skip' G_WHIP_YESNO 'Would you like to purge all WiFi related APT packages?\n\nAffected packages: iw wpasupplicant wireless-regdb' && G_AGP 'iw' 'wpasupplicant' 'wireless-regdb'
+ else
+ /boot/dietpi/func/dietpi-set_hardware wifimodules enable
+ fi
+ ;;
+ 'Onboard WiFi')
+ if Onboard_Wifi_Enabled
+ then
+ /boot/dietpi/func/dietpi-set_hardware wifimodules onboard_disable
+ else
+ /boot/dietpi/func/dietpi-set_hardware wifimodules onboard_enable
+ fi
+ ;;
+ 'IPv6') /boot/dietpi/func/dietpi-set_hardware enableipv6 $(( ! $ipv6_enabled ));;
+ 'Proxy') NEXT_MENU='proxy';;
+ 'Test') Menu_Test;;
+ *) NEXT_MENU="iface:$G_WHIP_RETURNED_VALUE";;
+ esac
+}
+
+Menu_Test()
+{
+ G_WHIP_DEFAULT_ITEM=$INTERNET_TEST_URL
+ G_WHIP_INPUTBOX 'Please enter a URL address to test, e.g.: https://dietpi.com' || return 0
+ INTERNET_TEST_URL=$G_WHIP_RETURNED_VALUE
+ if G_EXEC_NOHALT=1 G_CHECK_URL "$INTERNET_TEST_URL"
+ then
+ INTERNET_TEST_STATE=2
+ else
+ INTERNET_TEST_STATE=1
+ fi
+}
+
+Menu_Proxy()
+{
+ Load_Proxy_Vars
+ local state_text='Off'
+ (( $PROXY_ENABLED )) && state_text='On'
+ G_WHIP_MENU_ARRAY=(
+ 'State' ": [$state_text]"
+ 'Address' ": [$PROXY_ADDRESS]"
+ 'Port' ": [$PROXY_PORT]"
+ 'Username' ": [$PROXY_USERNAME]"
+ 'Password' ": [$PROXY_PASSWORD]"
+ )
+ G_WHIP_DEFAULT_ITEM=$PROXY_MENU_LASTITEM
+ G_WHIP_MENU 'Please select an option to adjust. Logout and login for changes to take effect.' || { Return_From_Submenu 'proxy'; return 0; }
+ PROXY_MENU_LASTITEM=$G_WHIP_RETURNED_VALUE
+ case $G_WHIP_RETURNED_VALUE in
+ 'State') (( $PROXY_ENABLED )) && PROXY_ENABLED=0 || PROXY_ENABLED=1;;
+ 'Address') G_WHIP_DEFAULT_ITEM=$PROXY_ADDRESS; G_WHIP_INPUTBOX 'Please enter the proxy URL or IP address\n - eg: MyProxy.com' && PROXY_ADDRESS=$G_WHIP_RETURNED_VALUE || return 0;;
+ 'Port') G_WHIP_DEFAULT_ITEM=$PROXY_PORT; G_WHIP_INPUTBOX 'Please enter the proxy port number\n - eg: 1234' && PROXY_PORT=$G_WHIP_RETURNED_VALUE || return 0;;
+ 'Username') G_WHIP_DEFAULT_ITEM=$PROXY_USERNAME; G_WHIP_INPUTBOX_REGEX='.*' G_WHIP_INPUTBOX 'Please enter the proxy username\n - Leave blank if not required' && PROXY_USERNAME=$G_WHIP_RETURNED_VALUE || return 0;;
+ 'Password') G_WHIP_DEFAULT_ITEM=$PROXY_PASSWORD; G_WHIP_INPUTBOX_REGEX='.*' G_WHIP_INPUTBOX 'Please enter the proxy password\n - Leave blank if not required' && PROXY_PASSWORD=$G_WHIP_RETURNED_VALUE || return 0;;
+ *) :;;
+ esac
+ Apply_Proxy_Settings
+}
+
+Menu_Interface()
+{
+ local iface=$1
+ [[ -d /sys/class/net/$iface ]] || { G_WHIP_MSG "Network interface '$iface' was not detected."; Return_From_Submenu "iface:$iface"; return 0; }
+ Load_Interface_State "$iface"
+ Net_Update_UsageStats "$iface"
+ local title=$(Interface_Menu_Title)
+ if [[ $CURRENT_IFACE_TYPE == 'eth' ]]
+ then
+ local speed='auto (default, recommended)'
+ [[ -f '/etc/systemd/system/ethtool_force_speed.service' ]] && grep -q "^WantedBy=ifup@$iface.service" /etc/systemd/system/ethtool_force_speed.service && speed=$(mawk '/^ExecStart=/{print $5;exit}' /etc/systemd/system/ethtool_force_speed.service)
+ G_WHIP_MENU_ARRAY=(
+ '' '●─ DHCP/STATIC IP '
+ 'Change Mode' ": [${CURRENT_IFACE_MODE^^}]"
+ )
+ [[ $CURRENT_IFACE_MODE == 'static' ]] && G_WHIP_MENU_ARRAY+=(
+ 'Copy' ': Copy current address to static'
+ 'Static IP' ": [$CURRENT_IFACE_IP_STATIC]"
+ 'Static Gateway' ": [$CURRENT_IFACE_GATEWAY_STATIC]"
+ 'Static DNS' ": [$CURRENT_IFACE_DNS_STATIC]"
+ )
+ G_WHIP_MENU_ARRAY+=(
+ '' '●─ Additional Options '
+ 'Link Speed' ": [$speed]"
+ 'Boot Mode' ": [${CURRENT_IFACE_BOOT_MODE#allow-}]"
+ )
+ if [[ $CURRENT_IFACE_SOURCE ]]
+ then
+ G_WHIP_MENU_ARRAY+=('' '●─ Toggle State ')
+ if (( $CURRENT_IFACE_ENABLED ))
+ then
+ G_WHIP_MENU_ARRAY+=('Disable' ': Stop and do not bring up interface at boot')
+ else
+ G_WHIP_MENU_ARRAY+=('Enable' ': Start and bring up interface at boot')
+ fi
+ G_WHIP_MENU_ARRAY+=('Remove' ': Remove this interface configuration entirely')
+ fi
+ G_WHIP_MENU_ARRAY+=(
+ '' '●─ Apply '
+ 'Save' ': Save all changes to be applied next reboot'
+ 'Apply' ': Save and apply all changes via interface restart'
+ )
+ G_WHIP_DEFAULT_ITEM=$IFACE_MENU_LASTITEM
+ G_WHIP_MENU "${title}\nUsage : Sent = $NET_TX_MB | Received = $NET_RX_MB\nAddress : $CURRENT_IFACE_IP | Gateway: $CURRENT_IFACE_GATEWAY | DNS: $DNS_CURRENT" || { Return_From_Submenu "iface:$iface"; return 0; }
+ IFACE_MENU_LASTITEM=$G_WHIP_RETURNED_VALUE
+ case $G_WHIP_RETURNED_VALUE in
+ 'Change Mode') [[ $CURRENT_IFACE_MODE == 'dhcp' ]] && CURRENT_IFACE_MODE='static' || CURRENT_IFACE_MODE='dhcp';;
+ 'Copy') Copy_Current_To_Static;;
+ 'Static IP') Change_StaticIp;;
+ 'Static Gateway') Change_StaticGateway;;
+ 'Static DNS') Change_StaticDns;;
+ 'Link Speed')
+ G_AG_CHECK_INSTALL_PREREQ ethtool
+ ip l s "$iface" up # enable link, sometimes needed for ethtool to fetch data
+ G_WHIP_MENU_ARRAY=(0 ': Auto-negotiation (default, recommended)')
+ while read -r item
+ do
+ item=${item//[^0-9]}
+ [[ $item ]] && G_WHIP_MENU_ARRAY+=("$item" ": Force $item Mbit link speed")
+ done < <(ethtool "$iface" | sed -n '/Supported link modes:/,/^[[:blank:]]*[[:alpha:]]/p' | head -n -1 | mawk '{print $NF}')
+ G_WHIP_DEFAULT_ITEM=$speed
+ if (( ${#G_WHIP_MENU_ARRAY[@]} > 2 ))
+ then
+ G_WHIP_MENU 'Please select a supported Ethernet link speed to force or auto-negotiation:' || return 0
+ else
+ G_WHIP_MENU_ARRAY+=(
+ 10 ': Force 10 Mbit link speed'
+ 100 ': Force 100 Mbit link speed'
+ 1000 ': Force 1000 Mbit link speed'
+ 2500 ': Force 2500 Mbit link speed'
+ )
+ G_WHIP_MENU 'WARNING: Supported link speeds for this adapter could not be obtained. Forcing an unsupported link speed might break connctivity.
+\nPlease select an Ethernet link speed to force or auto-negotiation:' || return 0
+ fi
+ /boot/dietpi/func/dietpi-set_hardware eth-forcespeed "$G_WHIP_RETURNED_VALUE" "$iface"
+ ;;
+ 'Boot Mode') Change_BootMode;;
+ 'Enable') CURRENT_IFACE_ENABLED=1; Apply_Current_Interface 1;;
+ 'Disable') CURRENT_IFACE_ENABLED=0; Apply_Current_Interface 1 && Return_From_Submenu "iface:$iface";;
+ 'Remove') Remove_Interface_Config "$iface"; Return_From_Submenu "iface:$iface";;
+ 'Save') Apply_Current_Interface;;
+ 'Apply') Apply_Current_Interface 1;;
+ *) :;;
+ esac
+ else
+ local description="${title}\nUsage : Sent = $NET_TX_MB | Received = $NET_RX_MB\n"
+ G_WHIP_MENU_ARRAY=('' '●─ Basic Options ')
+ if (( $CURRENT_IFACE_HOTSPOT ))
+ then
+ local status='Offline' hotspot_state_text='[Off] | Select to turn on hotspot'
+ (( $CURRENT_IFACE_HOTSPOT_ACTIVE )) && status='Online' hotspot_state_text='[On] | Select to turn off hotspot'
+ description+="Status : $status"
+ local hotspot_n_text='Off' hotspot_ac_text='Off' hotspot_ax_text='Off' hotspot_freq_text='2.4' hotspot_channel_text=$HOTSPOT_CHANNEL
+ (( $HOTSPOT_WIFI4 )) && hotspot_n_text='On'
+ (( $HOTSPOT_WIFI5 )) && hotspot_ac_text='On'
+ (( $HOTSPOT_WIFI6 )) && hotspot_ax_text='On'
+ if (( $HOTSPOT_5G ))
+ then
+ hotspot_freq_text='5'
+ hotspot_channel_text=$HOTSPOT_5G_CHANNEL
+ fi
+ G_WHIP_MENU_ARRAY+=(
+ 'SSID' ": [$HOTSPOT_SSID]"
+ 'Key' ": [$HOTSPOT_KEY]"
+ 'Frequency' ": [$hotspot_freq_text GHz]"
+ 'Channel' ": [$hotspot_channel_text]"
+ '802.11n' ": [$hotspot_n_text] WiFi 4 support"
+ '802.11ac' ": [$hotspot_ac_text] WiFi 5 support"
+ '802.11ax' ": [$hotspot_ax_text] WiFi 6 support"
+ )
+ else
+ local reconnect_text='Off'
+ (( $CURRENT_IFACE_WIFI_AUTO_RECONNECT )) && reconnect_text='On'
+ description+="SSID : $CURRENT_IFACE_WIFI_SSID | $CURRENT_IFACE_WIFI_BITRATE Mbit | Strength: $CURRENT_IFACE_WIFI_SIGNAL\nAddress : $CURRENT_IFACE_IP | Gateway: $CURRENT_IFACE_GATEWAY | DNS: $DNS_CURRENT"
+ G_WHIP_MENU_ARRAY+=(
+ 'Scan' ': Scan and configure SSIDs'
+ '' '●─ DHCP/STATIC IP '
+ 'Change Mode' ": [${CURRENT_IFACE_MODE^^}]"
+ )
+ [[ $CURRENT_IFACE_MODE == 'static' ]] && G_WHIP_MENU_ARRAY+=(
+ 'Copy' ': Copy current address to static'
+ 'Static IP' ": [$CURRENT_IFACE_IP_STATIC]"
+ 'Static Gateway' ": [$CURRENT_IFACE_GATEWAY_STATIC]"
+ 'Static DNS' ": [$CURRENT_IFACE_DNS_STATIC]"
+ )
+ fi
+ G_WHIP_MENU_ARRAY+=(
+ '' '●─ Additional Options '
+ 'Country' ": [$CURRENT_WIFI_COUNTRYCODE]"
+ 'Auto Reconnect' ": [$reconnect_text]"
+ 'Boot Mode' ": [${CURRENT_IFACE_BOOT_MODE#allow-}]"
+ )
+ if (( $CURRENT_IFACE_HOTSPOT ))
+ then
+ G_WHIP_MENU_ARRAY+=(
+ '' '●─ Toggle State '
+ 'State' ": $hotspot_state_text"
+ 'Uninstall' ': Uninstall WiFi Hotspot via dietpi-software'
+ )
+
+ elif [[ $CURRENT_IFACE_SOURCE ]]
+ then
+ G_WHIP_MENU_ARRAY+=('' '●─ Toggle State ')
+ if (( $CURRENT_IFACE_ENABLED ))
+ then
+ G_WHIP_MENU_ARRAY+=('Disable' ': Stop and do not bring up interface at boot')
+ else
+ G_WHIP_MENU_ARRAY+=('Enable' ': Start and bring up interface at boot')
+ fi
+ G_WHIP_MENU_ARRAY+=('Remove' ': Remove this interface configuration entirely')
+ fi
+ G_WHIP_MENU_ARRAY+=(
+ '' '●─ Apply '
+ 'Save' ': Save all changes to be applied next reboot'
+ 'Apply' ': Save and apply all changes via interface restart'
+ )
+ G_WHIP_DEFAULT_ITEM=$IFACE_MENU_LASTITEM
+ G_WHIP_MENU "$description" || { Return_From_Submenu "iface:$iface"; return 0; }
+ IFACE_MENU_LASTITEM=$G_WHIP_RETURNED_VALUE
+ case $G_WHIP_RETURNED_VALUE in
+ 'Scan') /boot/dietpi/func/dietpi-wifidb -i "$iface";;
+ 'Change Mode') [[ $CURRENT_IFACE_MODE == 'dhcp' ]] && CURRENT_IFACE_MODE='static' || CURRENT_IFACE_MODE='dhcp'; [[ $CURRENT_IFACE_MODE == 'static' ]] && G_WHIP_MSG 'When using STATIC IP, please ensure only one SSID entry exists in the scan menu.';;
+ 'Copy') Copy_Current_To_Static;;
+ 'Static IP') Change_StaticIp;;
+ 'Static Gateway') Change_StaticGateway;;
+ 'Static DNS') Change_StaticDns;;
+ 'Country') Change_WifiCountryCode;;
+ 'Auto Reconnect')
+ if (( $CURRENT_IFACE_WIFI_AUTO_RECONNECT ))
+ then
+ G_EXEC_NOEXIT=1 G_EXEC systemctl disable --now dietpi-wifi-monitor
+ else
+ G_EXEC_NOEXIT=1 G_EXEC systemctl enable --now dietpi-wifi-monitor
+ fi
+ ;;
+ 'Boot Mode') Change_BootMode;;
+ 'Enable') CURRENT_IFACE_ENABLED=1; Apply_Current_Interface 1;;
+ 'Disable') CURRENT_IFACE_ENABLED=0; G_EXEC_NOEXIT=1 G_EXEC systemctl disable --now dietpi-wifi-monitor; Apply_Current_Interface 1 && Return_From_Submenu "iface:$iface";;
+ 'Remove') G_EXEC_NOEXIT=1 G_EXEC systemctl disable --now dietpi-wifi-monitor; Remove_Interface_Config"$iface"; Return_From_Submenu "iface:$iface";;
+ 'Save') Apply_Current_Interface;;
+ 'Apply') Apply_Current_Interface 1;;
+ 'SSID') G_WHIP_DEFAULT_ITEM=$HOTSPOT_SSID; G_WHIP_INPUTBOX 'Please enter an SSID for your WiFi hotspot:' && HOTSPOT_SSID=$G_WHIP_RETURNED_VALUE;;
+ 'Key')
+ G_WHIP_INPUTBOX_REGEX='.{8}'
+ G_WHIP_INPUTBOX_REGEX_TEXT='at least 8 characters long'
+ G_WHIP_DEFAULT_ITEM=$HOTSPOT_KEY
+ G_WHIP_INPUTBOX 'Please enter a key/password with a minimum of 8 characters for your WiFi hotspot:' || return 0
+ HOTSPOT_KEY=$G_WHIP_RETURNED_VALUE
+ ;;
+ 'Frequency') HOTSPOT_5G=$(( ! $HOTSPOT_5G )); (( $HOTSPOT_5G && ! $HOTSPOT_WIFI5 && ! $HOTSPOT_WIFI6 )) && HOTSPOT_WIFI4=1;;
+ 'Channel')
+ if (( $HOTSPOT_5G ))
+ then
+ G_WHIP_DEFAULT_ITEM=$HOTSPOT_5G_CHANNEL
+ G_WHIP_INPUTBOX 'Please enter a 5 GHz WiFi channel for your hotspot:' && HOTSPOT_5G_CHANNEL=$G_WHIP_RETURNED_VALUE
+ else
+ local channel_mhz=2412
+ G_WHIP_MENU_ARRAY=()
+ for ((i=1; i<=13; i++))
+ do
+ G_WHIP_MENU_ARRAY+=("$i" ": $channel_mhz MHz")
+ ((channel_mhz+=5))
+ done
+ G_WHIP_DEFAULT_ITEM=$HOTSPOT_CHANNEL
+ G_WHIP_MENU 'Please select a 2.4 GHz WiFi channel for your hotspot:' && HOTSPOT_CHANNEL=$G_WHIP_RETURNED_VALUE
+ fi
+ ;;
+ '802.11n') HOTSPOT_WIFI4=$(( ! $HOTSPOT_WIFI4 )); (( $HOTSPOT_WIFI4 || $HOTSPOT_WIFI5 || $HOTSPOT_WIFI6 )) || HOTSPOT_5G=0;;
+ '802.11ac') HOTSPOT_WIFI5=$(( ! $HOTSPOT_WIFI5 )); (( $HOTSPOT_WIFI5 )) && HOTSPOT_5G=1; (( $HOTSPOT_WIFI4 || $HOTSPOT_WIFI5 || $HOTSPOT_WIFI6 )) || HOTSPOT_5G=0;;
+ '802.11ax') HOTSPOT_WIFI6=$(( ! $HOTSPOT_WIFI6 )); (( $HOTSPOT_WIFI4 || $HOTSPOT_WIFI5 || $HOTSPOT_WIFI6 )) || HOTSPOT_5G=0;;
+ 'State')
+ if (( $CURRENT_IFACE_HOTSPOT_ACTIVE ))
+ then
+ G_EXEC_NOEXIT=1 G_EXEC systemctl stop hostapd
+ else
+ G_EXEC_NOEXIT=1 G_EXEC systemctl start hostapd
+ fi
+ ;;
+ 'Uninstall') G_WHIP_YESNO 'Would you like to uninstall the WiFi Hotspot via dietpi-software?' && { export G_INIT_ALLOW_CONCURRENT=1; /boot/dietpi/dietpi-software uninstall 60 61; unset -v G_INIT_ALLOW_CONCURRENT; Return_From_Submenu "iface:$iface"; };;
+ *) :;;
+ esac
+ fi
+}
+
+Input()
+{
+ while (( $# ))
+ do
+ case $1 in
+ 'main') COMMAND='menu'; NEXT_MENU='main';;
+ 'country') COMMAND='menu' NEXT_MENU='country';;
+ 'proxy')
+ if (( $# == 1 ))
+ then
+ COMMAND='menu'
+ NEXT_MENU='proxy'
+ else
+ COMMAND='proxy'
+ shift
+ ACTION_VALUE=$1
+ shift
+ ACTION_EXTRA=$1
+ fi
+ ;;
+ 'apply')
+ COMMAND='apply'
+ shift
+ APPLY_IFACE=$1
+ [[ $APPLY_IFACE ]] || Error "Missing interface name for 'apply'.$USAGE"
+ ;;
+ 'remove')
+ COMMAND='remove'
+ shift
+ ACTION_VALUE=$1
+ [[ $ACTION_VALUE ]] || Error "Missing interface name for 'remove'.$USAGE"
+ ;;
+ '--enable') APPLY_ENABLE=1;;
+ '--disable') APPLY_ENABLE=0;;
+ '--dhcp') APPLY_MODE='dhcp';;
+ '--static') APPLY_MODE='static';;
+ '--ip') shift; APPLY_IP=$1;;
+ '--gateway') shift; APPLY_GATEWAY=$1;;
+ '--dns') shift; APPLY_DNS=$1;;
+ '--copy-current') APPLY_COPY_CURRENT=1;;
+ '--hotplug') APPLY_BOOT_MODE='hotplug';;
+ '--auto') APPLY_BOOT_MODE='auto';;
+ '--client') APPLY_ROLE='client';;
+ '--hotspot') APPLY_ROLE='hotspot';;
+ '--ssid') shift; APPLY_SSID=$1;;
+ '--key') shift; APPLY_KEY=$1;;
+ '--freq') shift; APPLY_FREQ=$1;;
+ '--channel') shift; APPLY_CHANNEL=$1;;
+ '--wifi4') shift; APPLY_WIFI4=$1;;
+ '--wifi5') shift; APPLY_WIFI5=$1;;
+ '--wifi6') shift; APPLY_WIFI6=$1;;
+ '--no-restart') APPLY_RESTART=0;;
+ '--force') APPLY_FORCE=1;;
+ '-h'|'--help'|'help') echo "$USAGE"; exit 0;;
+ *)
+ if [[ $COMMAND == 'menu' && $NEXT_MENU == 'main' ]]
+ then
+ NEXT_MENU="iface:$1"
+ else
+ Error "Invalid input ($1). Aborting ...$USAGE"
+ fi
+ ;;
+ esac
+ shift
+ done
+}
+
+Apply_From_CLI()
+{
+ [[ $APPLY_IFACE ]] || Error "Missing interface name for 'apply'.$USAGE"
+ (( $APPLY_FORCE )) || [[ -d /sys/class/net/$APPLY_IFACE ]] || Error "Network interface '$APPLY_IFACE' was not detected."
+ Load_Interface_State "$APPLY_IFACE"
+ [[ $APPLY_ENABLE ]] && CURRENT_IFACE_ENABLED=$APPLY_ENABLE
+ [[ $APPLY_MODE ]] && CURRENT_IFACE_MODE=$APPLY_MODE
+ [[ $APPLY_BOOT_MODE ]] && CURRENT_IFACE_BOOT_MODE=$APPLY_BOOT_MODE
+ (( $APPLY_COPY_CURRENT )) && Copy_Current_To_Static
+ if [[ $APPLY_IP ]]
+ then
+ CURRENT_IFACE_IP_STATIC=$APPLY_IP
+ [[ $CURRENT_IFACE_IP_STATIC == */* ]] || CURRENT_IFACE_IP_STATIC+='/24'
+ fi
+ [[ $APPLY_GATEWAY ]] && CURRENT_IFACE_GATEWAY_STATIC=$APPLY_GATEWAY
+ [[ $APPLY_DNS ]] && CURRENT_IFACE_DNS_STATIC=$APPLY_DNS
+ if [[ $CURRENT_IFACE_TYPE == 'wifi' && $APPLY_ROLE ]]
+ then
+ if [[ $APPLY_ROLE == 'hotspot' ]]
+ then
+ CURRENT_IFACE_HOTSPOT=1
+ CURRENT_IFACE_MODE='static'
+ [[ $APPLY_IP ]] || CURRENT_IFACE_IP_STATIC='192.168.42.1/24'
+ Load_Hotspot_Settings
+ else
+ CURRENT_IFACE_HOTSPOT=0
+ fi
+ fi
+ [[ $APPLY_SSID ]] && HOTSPOT_SSID=$APPLY_SSID
+ [[ $APPLY_KEY ]] && HOTSPOT_KEY=$APPLY_KEY
+ if [[ $APPLY_FREQ == '5' ]]
+ then
+ HOTSPOT_5G=1
+
+ elif [[ $APPLY_FREQ == '2.4' ]]
+ then
+ HOTSPOT_5G=0
+ fi
+ if [[ $APPLY_CHANNEL ]]
+ then
+ if (( $HOTSPOT_5G ))
+ then
+ HOTSPOT_5G_CHANNEL=$APPLY_CHANNEL
+ else
+ HOTSPOT_CHANNEL=$APPLY_CHANNEL
+ fi
+ fi
+ [[ $APPLY_WIFI4 == [01] ]] && HOTSPOT_WIFI4=$APPLY_WIFI4
+ [[ $APPLY_WIFI5 == [01] ]] && HOTSPOT_WIFI5=$APPLY_WIFI5
+ [[ $APPLY_WIFI6 == [01] ]] && HOTSPOT_WIFI6=$APPLY_WIFI6
+ Apply_Current_Interface "$APPLY_RESTART" || exit 1
+}
+
+Remove_Interface_Config()
+{
+ local iface=$1
+ ifdown --force "$iface" 2> /dev/null
+ [[ -f /etc/network/interfaces.d/$iface.conf ]] && G_EXEC rm "/etc/network/interfaces.d/$iface.conf"
+ Remove_Interface_From_Main_File "$iface"
+ return 0
+}
+
+Remove_From_CLI(){ Remove_Interface_Config "$ACTION_VALUE"; }
+
+Proxy_From_CLI()
+{
+ Load_Proxy_Vars
+ case $ACTION_VALUE in
+ 'enable') PROXY_ENABLED=1;;
+ 'disable') PROXY_ENABLED=0;;
+ 'address') PROXY_ADDRESS=$ACTION_EXTRA;;
+ 'port') PROXY_PORT=$ACTION_EXTRA;;
+ 'username') PROXY_USERNAME=$ACTION_EXTRA;;
+ 'password') PROXY_PASSWORD=$ACTION_EXTRA;;
+ *) Error "Invalid proxy action ($ACTION_VALUE).$USAGE";;
+ esac
+ Apply_Proxy_Settings
+}
+
+Menu_Loop()
+{
+ [[ $NEXT_MENU == "$ENTRY_MENU" ]] && G_WHIP_BUTTON_CANCEL_TEXT='Exit' || G_WHIP_BUTTON_CANCEL_TEXT='Back'
+ case $NEXT_MENU in
+ 'main') PRESERVE_SELECTED_SETTINGS=0; Menu_Main;; # load CURRENT_IFACE_* settings from config files again when entering this menu
+ 'iface:'*) Menu_Interface "${NEXT_MENU#iface:}"; PRESERVE_SELECTED_SETTINGS=1;; # do not override changed CURRENT_IFACE_* settings from values in config files while in this menu
+ 'country') Load_Interface_State "${WIFI_INTERFACES[0]:-wlan0}"; Change_WifiCountryCode; return 1;; # called via NEXT_MENU from CLI only
+ 'proxy') Menu_Proxy;;
+ 'exit') return 1;;
+ *) NEXT_MENU='main';;
+ esac
+ return 0
+}
+
+Input "$@"
+
+case $COMMAND in
+ 'apply') Apply_From_CLI; exit 0;;
+ 'remove') Remove_From_CLI; exit 0;;
+ 'proxy') Proxy_From_CLI; exit 0;;
+ 'menu') :;;
+ *) Error "Unknown command ($COMMAND).$USAGE";;
+esac
+
+ENTRY_MENU=$NEXT_MENU
+while Menu_Loop; do :; done
+
+exit 0
+}
diff --git a/dietpi/dietpi-software b/dietpi/dietpi-software
index 5ef7dc41ce..4b4668482d 100755
--- a/dietpi/dietpi-software
+++ b/dietpi/dietpi-software
@@ -4719,7 +4719,7 @@ _EOF_
if To_Install 114 # Nextcloud
then
- aDEPS=("php$PHP_VERSION-intl") # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
+ aDEPS=("php$PHP_VERSION-gmp" "php$PHP_VERSION-intl") # https://docs.nextcloud.com/server/stable/admin_manual/installation/php_configuration.html#recommended-general-php-modules
if [[ -f '/var/www/nextcloud/occ' ]]
then
@@ -4741,7 +4741,7 @@ _EOF_
[[ ${aDEPS[0]} ]] && { G_DIETPI-NOTIFY 2 'Installing required PHP modules'; G_AGI "${aDEPS[@]}"; aDEPS=(); }
G_DIETPI-NOTIFY 2 'Enabling required PHP modules'
- G_EXEC phpenmod ctype curl dom gd intl mbstring pdo_mysql posix simplexml xmlreader xmlwriter zip fileinfo opcache apcu redis exif
+ G_EXEC phpenmod ctype curl dom gd gmp intl mbstring pdo_mysql posix simplexml xmlreader xmlwriter zip fileinfo opcache apcu redis exif
G_DIETPI-NOTIFY 2 'Applying PHP override settings for Nextcloud' # https://docs.nextcloud.com/server/stable/admin_manual/installation/server_tuning.html#enable-php-opcache
local memory_consumption=$(sed -n '/^[[:blank:]]*opcache.memory_consumption=/{s/^[^=]*=//p;q}' "/etc/php/$PHP_VERSION/mods-available/dietpi.ini")
@@ -5253,9 +5253,9 @@ _EOF_
then
if (( $G_HW_MODEL < 10 ))
then
- # Enhance 4k support on RPi 4 and above with 512 MiB CMA
+ # Enhance 4k support on RPi 4 with 512 MiB CMA. Not needed from RPi 5 on: https://forums.raspberrypi.com/viewtopic.php?p=2385406#p2385532
local cma=()
- (( $G_HW_MODEL > 3 )) && cma=(512)
+ (( $G_HW_MODEL == 4 )) && cma=(512)
/boot/dietpi/func/dietpi-set_hardware rpi-opengl vc4-kms-v3d "${cma[@]}"
# Enable hardware codecs
@@ -7553,8 +7553,10 @@ _EOF_
aDEPS=("php$PHP_VERSION-curl" "php$PHP_VERSION-intl" "php$PHP_VERSION-xml")
# Download
+ # - Ampache 8 requires PHP 8.5+: https://github.com/ampache/ampache/releases#release-8.0.0
+ # - Hence, find latest asset for used PHP version among all releases.
local fallback_url="https://github.com/ampache/ampache/releases/download/7.10.1/ampache-7.10.1_all_php$PHP_VERSION.zip"
- Download_Install "$(curl -sSfL 'https://api.github.com/repos/ampache/ampache/releases/latest' | grep -Po "\"browser_download_url\": *\"\K[^\"]*\/ampache-[0-9\.]*_all_php$PHP_VERSION\.zip(?=\")")" ampache
+ Download_Install "$(curl -sSfL 'https://api.github.com/repos/ampache/ampache/releases' | grep -Po "\"browser_download_url\": *\"\K[^\"]*\/ampache-[0-9\.]*_all_php$PHP_VERSION\.zip(?=\")" | head -1)" ampache
# Reinstall: Preserve configs from old and new paths
[[ -f '/var/www/ampache/config/ampache.cfg.php' ]] && G_EXEC mv /var/www/ampache/config/ampache.cfg.php ampache/config/
@@ -7843,11 +7845,7 @@ _EOF_
if To_Install 60 # WiFi Hotspot
then
- local packages=('hostapd' 'isc-dhcp-server' 'iptables')
-
- G_AGI "${packages[@]}"
- G_EXEC systemctl stop hostapd isc-dhcp-server
- aSTART_SERVICES+=('hostapd' 'isc-dhcp-server')
+ G_AGI hostapd isc-dhcp-server iptables
Configure_iptables
# Unmask hostapd since it is masked via postinst when no config exists yet
@@ -7856,12 +7854,13 @@ _EOF_
# Enable WiFi modules
/boot/dietpi/func/dietpi-set_hardware wifimodules enable
+ # Detect interfaces
local eth_iface=$(G_GET_NET -t eth iface)
local wifi_iface=$(G_GET_NET -t wlan iface)
# DHCP server config
G_BACKUP_FP /etc/dhcp/dhcpd.conf
- cat << '_EOF_' > /etc/dhcp/dhcpd.conf
+ cat << '_EOF_' > /etc/dhcp/dhcpd.conf || exit 1
authoritative;
#default-lease-time 43200;
#max-lease-time 86400;
@@ -7877,30 +7876,6 @@ _EOF_
# Assign detected WLAN interface
G_EXEC eval "echo 'INTERFACESv4=\"$wifi_iface\"' > /etc/default/isc-dhcp-server"
- # Remove all entries below wlan, so we can recreate them
- G_EXEC sed --follow-symlinks -Ei '/(allow-hotplug|auto)[[:blank:]]+wlan/q0' /etc/network/interfaces
-
- # Enable up wlan
- G_CONFIG_INJECT 'allow-hotplug wlan' "allow-hotplug $wifi_iface" /etc/network/interfaces
-
- # Add WiFi settings to network interfaces config
- cat << _EOF_ >> /etc/network/interfaces
-iface $wifi_iface inet static
-address 192.168.42.1
-netmask 255.255.255.0
-#gateway 192.168.0.1
-#dns-nameservers 9.9.9.9 149.112.112.112
-pre-up iw dev $wifi_iface set power_save off
-post-down iw dev $wifi_iface set power_save on
-
-# iptables NAT rules
-up iptables-restore < /etc/iptables.ipv4.nat
-up ip6tables-restore < /etc/iptables.ipv6.nat
-_EOF_
- # Remove wireless-power setting if not supported by adapter/firmware
- # shellcheck disable=SC2015
- iw dev "$wifi_iface" set power_save on 2> /dev/null && iw dev "$wifi_iface" set power_save off 2> /dev/null || G_EXEC sed --follow-symlinks -i '/ iw dev .* set power_save /d' /etc/network/interfaces
-
# Access point config
# - Parse dietpi.txt
local ssid=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_SSID=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
@@ -7918,7 +7893,7 @@ _EOF_
# - WiFi 5 implies 5 GHz and 5 GHz requires at least WiFi 4
(( $wifi5 )) && freq5=1
(( $freq5 && ! $wifi5 && ! $wifi6 )) && wifi4=1
- # - Enable WMM with QoS if WiFi 4 or 5 is enabled
+ # - Enable WMM with QoS if WiFi 4, 5, or 6 is enabled
local wmm_enabled=0
(( $wifi4 || $wifi5 || $wifi6 )) && wmm_enabled=1
# - Apply mode channel based on frequency
@@ -7934,7 +7909,7 @@ _EOF_
fi
# - Create config
G_BACKUP_FP /etc/hostapd/hostapd.conf
- cat << _EOF_ > /etc/hostapd/hostapd.conf
+ cat << _EOF_ > /etc/hostapd/hostapd.conf || exit 1
interface=$wifi_iface
driver=nl80211
ssid=${ssid:-DietPi-Hotspot}
@@ -7972,12 +7947,11 @@ _EOF_
ip6tables -A FORWARD -i "$eth_iface" -o "$wifi_iface" -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -A FORWARD -i "$wifi_iface" -o "$eth_iface" -j ACCEPT
- # Save iptables rules, applied via /etc/network/interfaces
+ # Save iptables rules, applied via /etc/network/interfaces.d/.conf
iptables-save > /etc/iptables.ipv4.nat
ip6tables-save > /etc/iptables.ipv6.nat
- # Bring up interface now
- G_EXEC_NOHALT=1 G_EXEC ifup "$wifi_iface"
+ /boot/dietpi/dietpi-network apply "$wifi_iface" --enable --hotspot --ip 192.168.42.1/24
fi
if To_Install 61 tor # Tor Hotspot
@@ -8986,8 +8960,9 @@ sudo sysctl -p /etc/sysctl.d/dietpi-syncthing.confs
# RPi: Enable hardware codecs
(( $G_HW_MODEL > 9 )) || /boot/dietpi/func/dietpi-set_hardware rpi-codec 1
- # Flags: Allow root (disable sandbox) and minimise CPU usage: https://peter.sh/experiments/chromium-command-line-switches/
- G_EXEC eval "echo 'export CHROMIUM_FLAGS=\"\$CHROMIUM_FLAGS --no-sandbox --test-type --disable-smooth-scrolling --disable-low-res-tiling --enable-low-end-device-mode --num-raster-threads=$G_HW_CPU_CORES --disable-composited-antialiasing\"' > /etc/chromium.d/dietpi"
+ # Flags: Allow root to run Chromium (--no-sandbox), and mute the warning that "--no-sandbox" was used (--test-type)
+ # shellcheck disable=SC2016
+ G_EXEC eval 'echo '\''[ "$(id -u)" -eq 0 ] && export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --no-sandbox --test-type"'\'' > /etc/chromium.d/dietpi'
# Autostart script for kiosk mode, based on @AYapejian: https://github.com/MichaIng/DietPi/issues/1737#issue-318697621
G_EXEC mkdir -p /var/lib/dietpi/dietpi-software/installed
@@ -13972,6 +13947,7 @@ _EOF_
then
G_AGP hostapd isc-dhcp-server
+ # Remove hotspot config files
[[ -f '/etc/dhcp/dhcpd.conf' ]] && G_EXEC rm /etc/dhcp/dhcpd.conf
[[ -f '/etc/hostapd/hostapd.conf' ]] && G_EXEC rm /etc/hostapd/hostapd.conf
[[ -f '/etc/default/isc-dhcp-server' ]] && G_EXEC rm /etc/default/isc-dhcp-server
@@ -13980,26 +13956,11 @@ _EOF_
[[ -f '/etc/iptables.ipv6.nat' ]] && G_EXEC rm /etc/iptables.ipv6.nat
[[ -f '/etc/sysctl.d/dietpi-wifihotspot.conf' ]] && G_EXEC rm /etc/sysctl.d/dietpi-wifihotspot.conf
- # Set WiFi interface back to inactive and ready for use with dietpi-config.
- local wifi_iface=$(G_GET_NET -t wlan iface)
- # - Remove WLAN block, so we can recreate it
- G_EXEC sed --follow-symlinks -Ei '/(allow-hotplug|auto)[[:blank:]]+wlan/q0' /etc/network/interfaces
- # - Disable
- G_EXEC sed --follow-symlinks -i "/allow-hotplug wlan/c\#allow-hotplug $wifi_iface" /etc/network/interfaces
- # - Add default WiFi settings to network interfaces config
- cat << _EOF_ >> /etc/network/interfaces
-iface $wifi_iface inet dhcp
-address 192.168.0.101
-netmask 255.255.255.0
-#gateway 192.168.0.1
-#dns-nameservers 9.9.9.9 149.112.112.112
-pre-up iw dev $wifi_iface set power_save off
-post-down iw dev $wifi_iface set power_save on
-wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
-_EOF_
- # shellcheck disable=SC2015
- iw dev "$wifi_iface" set power_save on 2> /dev/null && iw dev "$wifi_iface" set power_save off 2> /dev/null || G_EXEC sed --follow-symlinks -i '/ iw dev .* set power_save /d' /etc/network/interfaces
- # - Flush iptables
+ # Remove interface configuration
+ local wifi_iface=$(G_GET_NET -q -t wlan iface)
+ [[ $wifi_iface ]] && /boot/dietpi/dietpi-network remove "$wifi_iface"
+
+ # Flush iptables
iptables -F
iptables -t nat -F
ip6tables -F
@@ -15273,94 +15234,19 @@ _EOF_
then
G_DIETPI-NOTIFY 2 'Applying DHCP leased network settings as static network settings'
- # Function to convert CIDR notation into dot-decimal notation
- cidr2mask()
- {
- local i mask full_octets=$(( $1 / 8 )) partial_octet=$(( $1%8 ))
- for i in {0..3}
- do
- if (( $i < $full_octets ))
- then
- mask+='255'
-
- elif (( $i == $full_octets ))
- then
- mask+=$(( 256 - 2 ** ( 8 - $partial_octet ) ))
- else
- mask+='0'
- fi
- (( $i < 3 )) && mask+=.
- done
- echo "$mask"
- }
-
- # Get Ethernet index
- local nameservers eth_index=$(sed -En '/^[[:blank:]]*(allow-hotplug|auto)[[:blank:]]+eth[0-9]+$/{s/^.*eth//p;q}' /etc/network/interfaces)
- # - Is enabled and uses DHCP
- if [[ $eth_index ]] && grep -Eq "^[[:blank:]]*iface[[:blank:]]+eth${eth_index}[[:blank:]]+inet[[:blank:]]+dhcp$" /etc/network/interfaces
- then
- G_DIETPI-NOTIFY 2 'Applying DHCP leased Ethernet settings as static Ethernet settings'
-
- # Get current network info
- local eth_ip=$(ip -br -f inet a s "eth$eth_index" | mawk '{print $3}' | sed 's|/.*$||')
- local eth_mask=$(cidr2mask "$(ip -br -f inet a s "eth$eth_index" | mawk '{print $3}' | sed 's|^.*/||')")
- local eth_gateway=$(ip r l dev "eth$eth_index" 0/0 | mawk '{print $3;exit}')
- nameservers=$(mawk '/^[[:blank:]]*nameserver[[:blank:]]/{print $2}' ORS=' ' /etc/resolv.conf)
-
- # Apply current network settings statically
- G_CONFIG_INJECT "iface[[:blank:]]+eth$eth_index" "iface eth$eth_index inet static" /etc/network/interfaces
- sed --follow-symlinks -i "0,\|^.*address[[:blank:]].*\$|s||address $eth_ip|" /etc/network/interfaces
- sed --follow-symlinks -i "0,\|^.*netmask[[:blank:]].*\$|s||netmask $eth_mask|" /etc/network/interfaces
- sed --follow-symlinks -i "0,\|^.*gateway[[:blank:]].*\$|s||gateway $eth_gateway|" /etc/network/interfaces
- fi
-
- # Get WiFi index
- local wlan_index=$(sed -En '/^[[:blank:]]*(allow-hotplug|auto)[[:blank:]]+wlan[0-9]+$/{s/^.*wlan//p;q}' /etc/network/interfaces)
- # - Is enabled and uses DHCP
- if [[ $wlan_index ]] && grep -Eq "^[[:blank:]]*iface[[:blank:]]+wlan${wlan_index}[[:blank:]]+inet[[:blank:]]+dhcp$" /etc/network/interfaces
- then
- G_DIETPI-NOTIFY 2 'Applying DHCP leased WiFi settings as static WiFi settings'
-
- # Get current network info
- local wlan_ip=$(ip -br -f inet a s "wlan$wlan_index" | mawk '{print $3}' | sed 's|/.*$||')
- local wlan_mask=$(cidr2mask "$(ip -br -f inet a s "wlan$wlan_index" | mawk '{print $3}' | sed 's|^.*/||')")
- local wlan_gateway=$(ip r l dev "wlan$wlan_index" 0/0 | mawk '{print $3;exit}')
- [[ $nameservers ]] || nameservers=$(mawk '/^[[:blank:]]*nameserver[[:blank:]]/{print $2}' ORS=' ' /etc/resolv.conf)
-
- # Apply current network settings statically
- G_CONFIG_INJECT "iface[[:blank:]]+wlan$wlan_index" "iface wlan$wlan_index inet static" /etc/network/interfaces
- sed --follow-symlinks -i "\|^iface wlan|,\$s|^.*address[[:blank:]].*\$|address $wlan_ip|" /etc/network/interfaces
- sed --follow-symlinks -i "\|^iface wlan|,\$s|^.*netmask[[:blank:]].*\$|netmask $wlan_mask|" /etc/network/interfaces
- sed --follow-symlinks -i "\|^iface wlan|,\$s|^.*gateway[[:blank:]].*\$|gateway $wlan_gateway|" /etc/network/interfaces
- fi
- unset -f cidr2mask
-
- # Apply DNS nameservers
- if [[ $nameservers ]]
- then
- G_DIETPI-NOTIFY 2 'Applying DHCP leased DNS nameservers as static nameservers'
-
- if command -v resolvconf > /dev/null
- then
- sed --follow-symlinks -i "/dns-nameservers[[:blank:]]/c\dns-nameservers ${nameservers% }" /etc/network/interfaces
- else
- sed --follow-symlinks -i "/dns-nameservers[[:blank:]]/c\#dns-nameservers ${nameservers% }" /etc/network/interfaces
- > /etc/resolv.conf
- for i in $nameservers; do echo "nameserver $i" >> /etc/resolv.conf; done
- fi
- fi
+ /boot/dietpi/dietpi-network apply "$(G_GET_NET iface)" --static --copy-current
G_DIETPI-NOTIFY 0 'Network changes will become effective with next reboot'
fi
# RPi: Disable onboard WiFi if WiFi modules were not enabled until now: https://github.com/MichaIng/DietPi/issues/5391
- [[ $G_HW_MODEL -gt 9 || ! -f '/etc/modprobe.d/dietpi-disable_wifi.conf' ]] || /boot/dietpi/func/dietpi-set_hardware wifimodules onboard_disable
+ [[ $G_HW_MODEL -le 9 && -f '/etc/modprobe.d/dietpi-disable_wifi.conf' ]] && /boot/dietpi/func/dietpi-set_hardware wifimodules onboard_disable
# Apply AutoStart choice
/boot/dietpi/dietpi-autostart "$AUTOINSTALL_AUTOSTARTTARGET"
# Disable console on TTY1 for purely headless SBCs, enabled for automated first run setup
- [[ $G_HW_MODEL =~ ^(47|48|55|56|57|59|60|64|65|73)$ ]] && G_EXEC systemctl --no-reload disable getty@tty1
+ [[ $G_HW_MODEL =~ ^(47|48|55|56|57|59|60|64|65|73|100|104)$ ]] && G_EXEC systemctl --no-reload disable getty@tty1
# Images are shipped with cron disabled, hence enable it now after first run setup has finished
G_EXEC systemctl enable cron
diff --git a/dietpi/func/dietpi-banner b/dietpi/func/dietpi-banner
index 0371e39ac9..5be782e377 100755
--- a/dietpi/func/dietpi-banner
+++ b/dietpi/func/dietpi-banner
@@ -304,16 +304,15 @@ $CLI_LINE"
}
local stat code
- if [[ $EUID == 0 ]]
+ if (( $EUID ))
then
- # Running as root
- stat=$(Get_Cert_Status_Raw 2>&1)
- code=$?
- else
# Running as non-root: Fail silently without NOPASSWD to avoid password prompt
stat=$(sudo -n dash -c "$(declare -f Get_Cert_Status_Raw); Get_Cert_Status_Raw 2>&1" 2> /dev/null)
- code=$?
+ else
+ # Running as root
+ stat=$(Get_Cert_Status_Raw 2>&1)
fi
+ code=$?
case $code in
0)
@@ -336,12 +335,26 @@ $CLI_LINE"
Get_Systemd_Status()
{
# Print systemd overall status based on "systemctl --failed"
- FAILED_CNT=$(systemctl --failed --no-legend --no-pager | wc -l 2> /dev/null)
- if [[ ! $FAILED_CNT || $FAILED_CNT == 0 ]]
+ # - non-root users can call systemctl if dbus is active
+ local failed_cnt
+ if [[ $EUID == 0 || -S '/run/dbus/system_bus_socket' ]]
then
- echo 'No services failed'
+ failed_cnt=$(systemctl --failed --legend=no --no-pager)
else
- echo "${aCOLOUR[alert]}$FAILED_CNT service(s) failed"
+ if ! failed_cnt=$(sudo -n systemctl --failed --legend=no --no-pager 2> /dev/null)
+ then
+ echo "${aCOLOUR[highlight]}NOPASSWD sudo required to obtain systemd status"
+ return 1
+ fi
+ fi
+
+ mapfile -t failed_cnt < <(echo -n "$failed_cnt")
+
+ if (( ${#failed_cnt[@]} ))
+ then
+ echo "${aCOLOUR[alert]}${#failed_cnt[@]} service(s) failed"
+ else
+ echo 'No services failed'
fi
}
@@ -352,12 +365,13 @@ $CLI_LINE"
if command -v fail2ban-client > /dev/null
then
# IP address detection (very sloppy for IPv6) - avoid {m,n} to support mawk on Debian Bookworm
- local IP_re='^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[0-9a-f:]*:[0-9a-f:]*)$'
- if [[ $EUID == 0 ]]
+ local IP_re='^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[0-9a-f:]*:[0-9a-f:]*)(/[0-9]+)?$'
+ if (( $EUID ))
then
- fail2ban-client banned 2> /dev/null | mawk -F\' -v ip="$IP_re" '{for(i=2;i /dev/null | mawk -F\' -v ip="$IP_re" '{for(i=2;i /dev/null | mawk -F\' -v ip="$IP_re" '{for(i=2;i /dev/null | mawk -F\' -v ip="$IP_re" '{for(i=2;i 20 ))
then
# high number of bans
- state="${aCOLOUR[alert]}$count_banned_ips IP(s) banned"
+ state="${aCOLOUR[alert]}$count_banned_ips ban(s)"
else
# low number of bans
- state="$count_banned_ips IP(s) banned"
+ state="$count_banned_ips ban(s)"
fi
;;
1) state="${aCOLOUR[alert]}fail2ban-client not available";;
@@ -450,7 +464,7 @@ $CLI_LINE"
mapfile -t ifaces < <("${ns_cmd_prefix[@]}" ip -br link 2> /dev/null | mawk '$1!="lo" {print $1}')
for iface in "${ifaces[@]}"
do
- # strip kernel-style peer suffix (e.g. eth0@if8) and use base name
+ # Strip "@foo" link/peer suffix which "ip" prints e.g. for veth and VLAN interfaces
iface=${iface%%@*}
case $iface in
@@ -508,7 +522,7 @@ For example: "/mnt/*" or "re:^/mnt/.*/*$"'
# Build mount list from findmnt (preserve findmnt order)
local -a available_mounts
- mapfile -t available_mounts < <(findmnt -nro TARGET --real 2>/dev/null)
+ mapfile -t available_mounts < <(findmnt -nro TARGET --fstab --real 2>/dev/null)
# Build quick lookup maps used to determine which mounts are present
# and which are configured by the user:
# - `avail_map`: mounts currently detected on the system
@@ -653,7 +667,7 @@ For example: "/mnt/*" or "re:^/mnt/.*/*$"'
# Pull all mounts once (-D -n -r) in bytes (-b). Rebuild TARGET safely
# (handles spaces) and compute USE% with one decimal using mawk from USED/SIZE.
# Use ASCII Unit Separator (0x1F) as a safe field delimiter to avoid collisions with mount names
- mapfile -t mount_lines < <(findmnt -b -Dnro TARGET,USED,SIZE --real | mawk -v SEP="$(printf '\037')" '{used=$(NF-1); size=$NF; target=$1; for(i=2;i<=NF-2;i++) target=target" "$i; perc=(size>0? used/size*100 : 0); printf "%s%s%s%s%s%s%s\n", target, SEP, used, SEP, size, SEP, sprintf("%.1f%%", perc)}')
+ mapfile -t mount_lines < <(findmnt -bnro TARGET,USED,SIZE --real | mawk -v SEP="$(printf '\037')" '{used=$(NF-1); size=$NF; target=$1; for(i=2;i<=NF-2;i++) target=target" "$i; perc=(size>0? used/size*100 : 0); printf "%s%s%s%s%s%s%s\n", target, SEP, used, SEP, size, SEP, sprintf("%.1f%%", perc)}')
# Keep mount_order[] to preserve findmnt's (consistent) order and aDISK_SPACE_PATTERNS' order.
for line in "${mount_lines[@]}"
@@ -1025,8 +1039,8 @@ For example: "/mnt/*" or "re:^/mnt/.*/*$"'
echo -e "$CLI_LINE\n"
(( ${aENABLED[credits]} )) && Print_Credits
- Print_Updates
(( ${aENABLED[dietpi_commands]} )) && Print_Useful_Commands
+ Print_Updates
}
Print_Banner()
diff --git a/dietpi/func/dietpi-globals b/dietpi/func/dietpi-globals
index c42ca6b362..b083249585 100644
--- a/dietpi/func/dietpi-globals
+++ b/dietpi/func/dietpi-globals
@@ -54,8 +54,8 @@
[[ -f '/boot/dietpi/.version' ]] && . /boot/dietpi/.version
# - Assign defaults/code version as fallback
[[ $G_DIETPI_VERSION_CORE ]] || G_DIETPI_VERSION_CORE=10
- [[ $G_DIETPI_VERSION_SUB ]] || G_DIETPI_VERSION_SUB=6
- [[ $G_DIETPI_VERSION_RC ]] || G_DIETPI_VERSION_RC=2
+ [[ $G_DIETPI_VERSION_SUB ]] || G_DIETPI_VERSION_SUB=7
+ [[ $G_DIETPI_VERSION_RC ]] || G_DIETPI_VERSION_RC=0
[[ $G_GITBRANCH ]] || G_GITBRANCH='master'
[[ $G_GITOWNER ]] || G_GITOWNER='MichaIng'
# - Save current version and Git branch
@@ -1393,15 +1393,34 @@ Press any key to continue...'
# A command is required
[[ $command ]] || { G_DIETPI-NOTIFY 1 "No command was given."; return 1; }
+ # Match an interface name against the requested type: "wlan" = has a wireless subdir, "eth" = has a device subdir but no wireless one, else fall back to prefix match
+ Type_Match()
+ {
+ [[ $type ]] || return 0
+ if [[ $type == 'wlan' ]]
+ then
+ [[ -d /sys/class/net/$1/wireless ]]
+
+ elif [[ $type == 'eth' ]]
+ then
+ local type
+ read -r type < "/sys/class/net/$1/type" 2> /dev/null
+ [[ $type == 1 && ! ( -d /sys/class/net/$1/bridge || -d /sys/class/net/$1/bonding || -e /sys/class/net/$1/tun_flags ) ]]
+ else
+ [[ $1 == $type* ]]
+ fi
+ }
+ trap 'unset -f Type_Match' RETURN
+
# Early return if given interface does not exists or does not match given type
if [[ $iface ]]
then
- if [[ ! -e /sys/class/net/$iface ]]
+ if [[ ! -d /sys/class/net/$iface ]]
then
(( $quite )) || G_DIETPI-NOTIFY 1 "The given interface \"$iface\" does not exist."
return 1
- elif [[ $type && $iface != $type* ]]
+ elif ! Type_Match "$iface"
then
(( $quite )) || G_DIETPI-NOTIFY 1 "The given interface \"$iface\" is not of type \"$type\"."
return 1
@@ -1425,7 +1444,7 @@ Press any key to continue...'
if [[ $gateway ]]
then
# Check for interface type
- if [[ $type && $if != $type* ]]
+ if ! Type_Match "$if"
then
(( $quite )) || G_DIETPI-NOTIFY 1 "The default gateway is not assigned to any interface of type \"$type\"."
return 1
@@ -1439,7 +1458,7 @@ Press any key to continue...'
fi
# Print interface/IP address if matching default gateway was found
- if [[ $gateway && ( ! $type || $if == $type* ) ]]
+ if [[ $gateway ]] && Type_Match "$if"
then
iface=$if
# shellcheck disable=SC2086
@@ -1455,7 +1474,8 @@ Press any key to continue...'
then
while read -r if state mac details
do
- [[ $if == 'eth'[0-9]* ]] || continue
+ if=${if%%@*} # Strip "@foo" link/peer suffix which "ip" prints e.g. for veth and VLAN interfaces
+ Type_Match "$if" || continue
[[ $state == 'UP' || $details == *'UP'* ]] && { aiface=(); break; }
aiface+=("$if")
@@ -1474,8 +1494,9 @@ Press any key to continue...'
# shellcheck disable=SC2086
while read -r if state ip
do
+ if=${if%%@*} # Strip "@foo" link/peer suffix which "ip" prints e.g. for veth and VLAN interfaces
[[ $if == 'lo' ]] && continue
- [[ $type && $if != $type* ]] && continue
+ Type_Match "$if" || continue
# Cut off secondary IP addresses and CIDR mask
ip=${ip%%/*}
diff --git a/dietpi/func/dietpi-obtain_hw_model b/dietpi/func/dietpi-obtain_hw_model
index 5aaaf35435..8d185adba0 100755
--- a/dietpi/func/dietpi-obtain_hw_model
+++ b/dietpi/func/dietpi-obtain_hw_model
@@ -97,6 +97,7 @@
18) G_HW_MODEL_NAME='RPi CM5' G_HW_MODEL=5;;
19) G_HW_MODEL_NAME='RPi 500/500+' G_HW_MODEL=5 G_HW_ONBOARD_WIFI=1;;
1a) G_HW_MODEL_NAME='RPi CM5 Lite' G_HW_MODEL=5;;
+ 1b) G_HW_MODEL_NAME='RPi CM Zero' G_HW_MODEL=3 G_HW_ONBOARD_WIFI=1;; # onboard WiFi is optional
*) :;;
esac
# Manufacturer
diff --git a/dietpi/func/dietpi-set_hardware b/dietpi/func/dietpi-set_hardware
index a38ba7f36f..00147b49bc 100755
--- a/dietpi/func/dietpi-set_hardware
+++ b/dietpi/func/dietpi-set_hardware
@@ -508,16 +508,17 @@ _EOF_
}
#/////////////////////////////////////////////////////////////////////////////////////
- # eth-forcespeed: Ethernet force link speed
+ # eth-forcespeed
#/////////////////////////////////////////////////////////////////////////////////////
Eth_Force_Speed_Main()
{
if disable_error=1 G_CHECK_VALIDINT "$INPUT_DEVICE_VALUE" 1
then
local speed_mbit=$INPUT_DEVICE_VALUE
- local iface=$(G_GET_NET -t eth iface)
+ local iface=${INPUT_ADDITIONAL:-$(G_GET_NET -t eth iface)}
+ [[ $iface ]] || { G_DIETPI-NOTIFY 1 'No Ethernet interface has been detected. Aborting ...'; return 1; }
- cat << _EOF_ > /etc/systemd/system/ethtool_force_speed.service
+ cat << _EOF_ > /etc/systemd/system/ethtool_force_speed.service || return 1
[Unit]
Description=Enforce $speed_mbit Mbit on $iface via ethtool (DietPi)
Wants=network-online.target
@@ -540,7 +541,7 @@ _EOF_
G_EXEC systemctl disable --now ethtool_force_speed
G_EXEC rm /etc/systemd/system/ethtool_force_speed.service
fi
- [[ -d '/etc/systemd/system/ethtool_force_speed.service.d' ]] && G_EXEC rm -R /etc/systemd/system/ethtool_force_speed.service.d
+ [[ ! -d '/etc/systemd/system/ethtool_force_speed.service.d' ]] || G_EXEC rm -R /etc/systemd/system/ethtool_force_speed.service.d
else
Unknown_Input_Mode
fi
@@ -1046,7 +1047,7 @@ _EOF_
}
#/////////////////////////////////////////////////////////////////////////////////////
- # I2C
+ # i2c
#/////////////////////////////////////////////////////////////////////////////////////
I2c_Main(){
@@ -1093,7 +1094,7 @@ _EOF_
}
#/////////////////////////////////////////////////////////////////////////////////////
- # SPI: https://github.com/raspberrypi/documentation/tree/master/hardware/raspberrypi/spi
+ # spi: https://github.com/raspberrypi/documentation/tree/master/hardware/raspberrypi/spi
#/////////////////////////////////////////////////////////////////////////////////////
SPI_Main()
{
@@ -1142,7 +1143,7 @@ _EOF_
}
#/////////////////////////////////////////////////////////////////////////////////////
- # Bluetooth
+ # bluetooth
#/////////////////////////////////////////////////////////////////////////////////////
Bluetooth_Main()
{
@@ -1246,7 +1247,7 @@ _EOF_
}
#/////////////////////////////////////////////////////////////////////////////////////
- # Network
+ # enableipv6
#/////////////////////////////////////////////////////////////////////////////////////
Enable_IPv6(){
@@ -1301,6 +1302,9 @@ _EOF_
}
+ #/////////////////////////////////////////////////////////////////////////////////////
+ # wifimodules
+ #/////////////////////////////////////////////////////////////////////////////////////
Wifi_Modules_Main(){
# Estimate module list
@@ -1423,6 +1427,9 @@ _EOF_
}
+ #/////////////////////////////////////////////////////////////////////////////////////
+ # wificountrycode
+ #/////////////////////////////////////////////////////////////////////////////////////
Wifi_Countrycode_Main()
{
# No input: Apply dietpi.txt setting
@@ -2135,7 +2142,7 @@ _EOF_
}
#/////////////////////////////////////////////////////////////////////////////////////
- # GPU Driver
+ # gpudriver
# INPUT_DEVICE_VALUE
# - none (uninstall)
# - intel
@@ -2206,6 +2213,9 @@ _EOF_
G_CONFIG_INJECT 'CONFIG_GPU_DRIVER=' "CONFIG_GPU_DRIVER=$INPUT_DEVICE_VALUE" /boot/dietpi.txt
}
+ #/////////////////////////////////////////////////////////////////////////////////////
+ # qemu-guest-agent
+ #/////////////////////////////////////////////////////////////////////////////////////
QEMU_Guest_Agent_Main()
{
(( $G_HW_MODEL == 20 )) || { Unsupported_Input_Name; return 1; } # VM only
@@ -2221,6 +2231,9 @@ _EOF_
G_EXEC systemctl start qemu-guest-agent
}
+ #/////////////////////////////////////////////////////////////////////////////////////
+ # keyboard
+ #/////////////////////////////////////////////////////////////////////////////////////
Keyboard_Main()
{
until [[ -f '/usr/share/X11/xkb/rules/base.lst' ]]
@@ -2267,7 +2280,11 @@ _EOF_
G_EXEC_OUTPUT=1 G_EXEC_NOHALT=1 G_EXEC dpkg-reconfigure -f noninteractive keyboard-configuration || return $?
fi
- G_EXEC_OUTPUT=1 G_EXEC_NOHALT=1 G_EXEC setupcon --save # https://bugs.debian.org/818065
+ # Bookworm: Workaround for: https://bugs.debian.org/818065
+ # - Update /etc/console-setup/cached_* with --save-only first, and setup console in a 2nd call.
+ # - Using "--save" throws 4x WARNING: Unknown X keysym "dead_belowmacron", as it seems to setup the console first, and update the cache afterwards.
+ G_EXEC_OUTPUT=1 G_EXEC_NOHALT=1 G_EXEC setupcon --save-only
+ G_EXEC_OUTPUT=1 G_EXEC_NOHALT=1 G_EXEC setupcon
G_CONFIG_INJECT 'AUTO_SETUP_KEYBOARD_LAYOUT=' "AUTO_SETUP_KEYBOARD_LAYOUT=$G_WHIP_RETURNED_VALUE" /boot/dietpi.txt
}
@@ -2288,7 +2305,7 @@ _EOF_
'spi') SPI_Main;;
'lcdpanel') Lcd_Panel_Main || EXIT_CODE=1;;
'rpi-opengl') RPi_OpenGL_Main;;
- 'eth-forcespeed') Eth_Force_Speed_Main;;
+ 'eth-forcespeed') Eth_Force_Speed_Main || EXIT_CODE=1;;
'remoteir') RemoteIR_Main;;
'gpumemsplit') Gpu_Memory_Split_Main;;
'rpi-camera') RPi_Camera_Main;;
diff --git a/dietpi/func/dietpi-set_software b/dietpi/func/dietpi-set_software
index 650d7df06d..54bf9f9ed2 100755
--- a/dietpi/func/dietpi-set_software
+++ b/dietpi/func/dietpi-set_software
@@ -13,20 +13,20 @@
readonly FP_SCRIPT='/boot/dietpi/func/dietpi-set_software'
readonly AVAIABLE_COMMANDS="
Available commands:
-$FP_SCRIPT locale xx_XX.UTF-8 (eg: en_GB.UTF-8)
-$FP_SCRIPT allo eth_dhcp|eth_static [] [] [] []
-$FP_SCRIPT useradd X=create user with name X and default permissions, using global DietPi password (dietpi)
-$FP_SCRIPT apt-mirror |default
-$FP_SCRIPT apt clean|reset|cache|lists|archives|compress [enable|disable|ram|disk]
-$FP_SCRIPT ntpd-mode [0-4] Time sync modes: 0=custom|1=boot|2=boot+daily|3=boot+hourly|4=daemon+drift
-$FP_SCRIPT timesync-mirror Apply network time sync mirror from dietpi.txt
-$FP_SCRIPT verify_dietpi.txt Verifies dietpi.txt entries, adds missing entries if required
-$FP_SCRIPT password users|software [check] Change passwords for \"root\" and \"dietpi\" users, respectively the global software password [if default is still applied].
-$FP_SCRIPT boot_wait_for_network [01] Enable or disable waiting for network interface configuration before DietPi-PostBoot is started, including postboot.d custom scripts and service startups
-$FP_SCRIPT add_ssh_pubkeys
-$FP_SCRIPT disable_ssh_password_logins [01]|root| Whether to disable SSH password logins for all users or root only; Leave empty to apply setting from /boot/dietpi.txt
-$FP_SCRIPT rpi_firmware_migration Migrate to the new Raspberry Pi kernel/firmware stack. Supported on Debian Bookworm or newer on Raspberry Pi only.
-$FP_SCRIPT rpi_kernel_choice Supported on Debian Bookworm or newer on Raspberry Pi only
+$FP_SCRIPT locale xx_XX.UTF-8 (eg: en_GB.UTF-8)
+$FP_SCRIPT allo (deprecated) eth_dhcp|eth_static [] [] [] [] (use dietpi-network CLI instead)
+$FP_SCRIPT useradd X=create user with name X and default permissions, using global DietPi password (dietpi)
+$FP_SCRIPT apt-mirror |default
+$FP_SCRIPT apt clean|reset|cache|lists|archives|compress [enable|disable|ram|disk]
+$FP_SCRIPT ntpd-mode [0-4] Time sync modes: 0=custom|1=boot|2=boot+daily|3=boot+hourly|4=daemon+drift
+$FP_SCRIPT timesync-mirror Apply network time sync mirror from dietpi.txt
+$FP_SCRIPT verify_dietpi.txt Verifies dietpi.txt entries, adds missing entries if required
+$FP_SCRIPT password users|software [check] Change passwords for \"root\" and \"dietpi\" users, respectively the global software password [if default is still applied].
+$FP_SCRIPT boot_wait_for_network [01] Enable or disable waiting for network interface configuration before DietPi-PostBoot is started, including postboot.d custom scripts and service startups
+$FP_SCRIPT add_ssh_pubkeys
+$FP_SCRIPT disable_ssh_password_logins [01]|root| Whether to disable SSH password logins for all users or root only; Leave empty to apply setting from /boot/dietpi.txt
+$FP_SCRIPT rpi_firmware_migration Migrate to the new Raspberry Pi kernel/firmware stack. Supported on Debian Bookworm or newer on Raspberry Pi only.
+$FP_SCRIPT rpi_kernel_choice Supported on Debian Bookworm or newer on Raspberry Pi only
" #////////////////////////////////////
# Inputs
@@ -514,31 +514,20 @@ deb $INPUT_MODE_VALUE $G_DISTRO_NAME-backports main contrib non-free non-free-fi
}
#/////////////////////////////////////////////////////////////////////////////////////
- # allo
+ # allo: deprecated: use dietpi-network CLI instead
#/////////////////////////////////////////////////////////////////////////////////////
Allo_Main()
{
+ local iface=$(G_GET_NET -t eth iface)
if [[ $INPUT_MODE_VALUE == 'eth_dhcp' ]]
then
- G_CONFIG_INJECT 'iface eth' 'iface eth0 inet dhcp' /etc/network/interfaces
- sed --follow-symlinks -i '0,/^.*dns-nameservers[[:blank:]].*$/s//#dns-nameservers 9.9.9.9 149.112.112.112/' /etc/network/interfaces
+ /boot/dietpi/dietpi-network apply "$iface" --dhcp --no-restart
elif [[ $INPUT_MODE_VALUE == 'eth_static' ]]
then
- G_CONFIG_INJECT 'iface eth' 'iface eth0 inet static' /etc/network/interfaces
- [[ $INPUT_ADDITIONAL_1 ]] && sed --follow-symlinks -i "0,\|^.*address[[:blank:]].*\$|s||address $INPUT_ADDITIONAL_1|" /etc/network/interfaces
- [[ $INPUT_ADDITIONAL_2 ]] && sed --follow-symlinks -i "0,\|^.*gateway[[:blank:]].*\$|s||gateway $INPUT_ADDITIONAL_2|" /etc/network/interfaces
- [[ $INPUT_ADDITIONAL_3 ]] && sed --follow-symlinks -i "0,\|^.*netmask[[:blank:]].*\$|s||netmask $INPUT_ADDITIONAL_3|" /etc/network/interfaces
- [[ $INPUT_ADDITIONAL_4 ]] || return 0
- if command -v resolvconf > /dev/null
- then
- sed --follow-symlinks -i "0,\|^.*dns-nameservers[[:blank:]].*\$|s||dns-nameservers $INPUT_ADDITIONAL_4|" /etc/network/interfaces
- else
- sed --follow-symlinks -i "0,\|^.*dns-nameservers[[:blank:]].*\$|s||#dns-nameservers $INPUT_ADDITIONAL_4|" /etc/network/interfaces
- > /etc/resolv.conf
- local i
- for i in $INPUT_ADDITIONAL_4; do echo "nameserver $i" >> /etc/resolv.conf; done
- fi
+ local ip=$INPUT_ADDITIONAL_1 gateway=$INPUT_ADDITIONAL_2 mask=$INPUT_ADDITIONAL_3 dns=$INPUT_ADDITIONAL_4
+ [[ $ip && $mask ]] && ip+=$(mawk -v m="$mask" 'BEGIN{n=split(m,a,"."); bits=0; for(i=1;i<=n;i++) {v=a[i]; while(v>0) {bits+=v%2;v=int(v/2)}}; print "/" bits}')
+ /boot/dietpi/dietpi-network apply "$iface" --static ${ip:+--ip "$ip"} ${gateway:+--gateway "$gateway"} ${dns:+--dns "$dns"} --no-restart
else
Unknown_Input_Mode
fi
diff --git a/dietpi/func/dietpi-wifidb b/dietpi/func/dietpi-wifidb
index 7556f8d986..dbfdbd5029 100755
--- a/dietpi/func/dietpi-wifidb
+++ b/dietpi/func/dietpi-wifidb
@@ -8,17 +8,27 @@
# Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com
#
#////////////////////////////////////
- #
- # Usage:
- readonly FP_SCRIPT='/boot/dietpi/func/dietpi-wifidb'
- readonly AVAIABLE_COMMANDS="
-Available commands
-$FP_SCRIPT Menu
-$FP_SCRIPT 1 Applies WiFi creds from DB store to system
-" #////////////////////////////////////
+ # Location: /boot/dietpi/dietpi-network
+ readonly USAGE='
+Usage: dietpi-wifidb [-i ] []
+Available commands:
+ Interactive menu to manage WiFi networks
+ 1 Applies WiFi credentials from dietpi-wifi.txt/dietpi-wifi.db
+Available options for interative menu:
+ -i : Use given WiFi interface to scan for networks instead of auto-detecting one
+' #////////////////////////////////////
# Grab Input
- INPUT=$*
+ INPUT=
+ WIFI_IFACE=
+ while (( $# ))
+ do
+ case $1 in
+ '-i') shift; WIFI_IFACE=$1;;
+ *) INPUT=$1;;
+ esac
+ shift
+ done
EXIT_CODE=0
# Import DietPi-Globals --------------------------------------------------------------
@@ -206,7 +216,7 @@ _EOF_
Scan_Wifi()
{
- local wifi_iface=$(G_GET_NET -t wlan iface)
+ local wifi_iface=${WIFI_IFACE:-$(G_GET_NET -t wlan iface)}
# Return if no WiFi adapter is detected
[[ $wifi_iface ]] || { G_WHIP_MSG 'No WiFi adapter was detected on your device. Scanning for interfaces cannot be done.'; return 1; }
@@ -339,7 +349,7 @@ _EOF_
then
Wifi_Db_Apply
else
- G_DIETPI-NOFITY 1 "Unknown input argument: $INPUT\n$AVAIABLE_COMMANDS"
+ G_DIETPI-NOFITY 1 "Unknown input argument: $INPUT\n$USAGE"
EXIT_CODE=1
fi
#-----------------------------------------------------------------------------------
diff --git a/rootfs/etc/bashrc.d/dietpi.bash b/rootfs/etc/bashrc.d/dietpi.bash
index 64f856a08f..a0ca55d727 100644
--- a/rootfs/etc/bashrc.d/dietpi.bash
+++ b/rootfs/etc/bashrc.d/dietpi.bash
@@ -18,7 +18,7 @@
[[ -t 0 && $- == *'i'* ]] || return 0
# DietPi-Globals: dietpi-* aliases, G_* functions and variables
- . /boot/dietpi/func/dietpi-globals || { echo -e '[\e[31mFAILED\e[0m] DietPi-Login | Failed to load DietPi-Globals. Skipping DietPi login scripts...'; return 1; }
+ . /boot/dietpi/func/dietpi-globals || { echo -e '[\e[31mFAILED\e[0m] DietPi-Login | Failed to load DietPi-Globals. Skipping DietPi login scripts...' >&2; return 1; }
# Aliases
# - sudo alias that allows running other aliases with "sudo": https://github.com/MichaIng/DietPi/issues/424
@@ -49,6 +49,7 @@
alias dietpi-cloudshell='/boot/dietpi/dietpi-cloudshell'
alias dietpi-vpn='/boot/dietpi/dietpi-vpn'
alias dietpi-ddns='/boot/dietpi/dietpi-ddns'
+ alias dietpi-network='/boot/dietpi/dietpi-network'
alias dietpi-display='/boot/dietpi/dietpi-display'
alias dietpi-benchmark='/boot/dietpi/dietpi-benchmark'
alias cpu='/boot/dietpi/dietpi-cpuinfo'
@@ -61,7 +62,7 @@
# - 1337 moments ;)
alias 1337='echo "Indeed, you are =)"'
- # "G_DIETPI-NOFITY -2 message" starts a process animation. If scripts fail to kill the animation, e.g. cancelled by user, terminal bash prompt has to do it as last resort.
+ # "G_DIETPI-NOTIFY -2 message" starts a process animation. If scripts fail to kill the animation, e.g. cancelled by user, terminal bash prompt has to do it as last resort.
[[ $PROMPT_COMMAND == *'dietpi-process.pid'* ]] || PROMPT_COMMAND="[[ -w '/tmp/dietpi-process.pid' ]] && rm -f /tmp/dietpi-process.pid &> /dev/null && echo -ne '\r\e[J'; $PROMPT_COMMAND"
# Workaround if SSH client overrides locale with "POSIX" fallback: https://github.com/MichaIng/DietPi/issues/1540#issuecomment-367066178
diff --git a/rootfs/var/lib/dietpi/services/dietpi-firstboot.bash b/rootfs/var/lib/dietpi/services/dietpi-firstboot.bash
index 756d4932c3..f04e3289af 100755
--- a/rootfs/var/lib/dietpi/services/dietpi-firstboot.bash
+++ b/rootfs/var/lib/dietpi/services/dietpi-firstboot.bash
@@ -144,6 +144,17 @@
grep -q '^[[:blank:]]*fdtoverlays[[:blank:]]' /boot/extlinux/extlinux.conf && { reboot; exit 0; }
fi
+ # GRUB BIOS: Set install device: https://github.com/MichaIng/DietPi/issues/4542
+ if dpkg-query -s 'grub-pc' 2> /dev/null | grep -q '^Status: install ok installed$'
+ then
+ local root_drive=$(lsblk -npo PKNAME "$(findmnt -Ufvnro SOURCE /)")
+ if [[ $root_drive == '/dev/'* ]]
+ then
+ G_DIETPI-NOTIFY 2 "Applying the rootfs parent drive \"$root_drive\" as GRUB install target"
+ debconf-set-selections <<< "grub-pc grub-pc/install_devices multiselect $root_drive"
+ fi
+ fi
+
# End user automated script
if [[ -f '/boot/Automation_Custom_PreScript.sh' ]]
then
@@ -190,8 +201,8 @@ _EOF_
/boot/dietpi/func/dietpi-set_software apt-mirror "$(sed -n "/^[[:blank:]]*$target_repo=/{s/^[^=]*=//p;q}" /boot/dietpi.txt)"
# Recreate machine-id: https://github.com/MichaIng/DietPi/issues/2015
- [[ -f '/etc/machine-id' ]] && rm /etc/machine-id
- [[ -f '/var/lib/dbus/machine-id' ]] && rm /var/lib/dbus/machine-id
+ G_DIETPI-NOTIFY 2 'Resetting machine ID'
+ rm -v /etc/machine-id /var/lib/dbus/machine-id
systemd-machine-id-setup
# Apply time zone
@@ -214,24 +225,26 @@ _EOF_
/boot/dietpi/func/dietpi-set_software locale "$autoinstall_language"
fi
- # Skip keyboard, SSH, serial console and network setup on container systems
- (( $G_HW_MODEL == 75 )) && return 0
-
# Apply keyboard layout
- /boot/dietpi/func/dietpi-set_hardware keyboard autosetup
+ dpkg-query -s 'console-setup' 2> /dev/null | grep -q '^Status: install ok installed$' && /boot/dietpi/func/dietpi-set_hardware keyboard autosetup
# Disable serial console if set in dietpi.txt
grep -q '^[[:blank:]]*CONFIG_SERIAL_CONSOLE_ENABLE=0' /boot/dietpi.txt && /boot/dietpi/func/dietpi-set_hardware serialconsole disable
# Regenerate unique Dropbear host keys
- local i type
- for i in /etc/dropbear/dropbear_*_host_key
- do
- type=${i#/etc/dropbear/dropbear_}
- type=${type%_host_key}
- rm -v "$i"
- dropbearkey -t "$type" -f "$i"
- done
+ # ToDo: Do as well for OpenSSH if installed
+ if dpkg-query -s 'dropbear-bin' 2> /dev/null | grep -q '^Status: install ok installed$'
+ then
+ G_DIETPI-NOTIFY 2 'Regenerating unique Dropbear SSH server host keys'
+ local i type
+ for i in /etc/dropbear/dropbear_*_host_key
+ do
+ type=${i#/etc/dropbear/dropbear_}
+ type=${type%_host_key}
+ rm -v "$i"
+ dropbearkey -t "$type" -f "$i"
+ done
+ fi
# Apply SSH pubkey(s) from dietpi.txt
/boot/dietpi/func/dietpi-set_software add_ssh_pubkeys
@@ -239,99 +252,76 @@ _EOF_
# Apply SSH password login setting
/boot/dietpi/func/dietpi-set_software disable_ssh_password_logins
- # Apply forced Ethernet link speed if set in dietpi.txt
- /boot/dietpi/func/dietpi-set_hardware eth-forcespeed "$(sed -n '/^[[:blank:]]*AUTO_SETUP_NET_ETH_FORCE_SPEED=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)"
-
- # Network setup
- # - Grab available network interfaces
- local iface_eth=$(G_GET_NET -q -t eth iface)
- [[ $iface_eth ]] || iface_eth='eth0'
- local iface_wlan=$(G_GET_NET -q -t wlan iface)
- [[ $iface_wlan ]] || iface_wlan='wlan0'
-
- # - Replace interface names with the ones obtained above
- sed --follow-symlinks -i "s/eth[0-9]/$iface_eth/g" /etc/network/interfaces
- sed --follow-symlinks -i "s/wlan[0-9]/$iface_wlan/g" /etc/network/interfaces
-
- # - Grab user requested settings from dietpi.txt
- local ethernet_enabled=$(grep -cm1 '^[[:blank:]]*AUTO_SETUP_NET_ETHERNET_ENABLED=1' /boot/dietpi.txt)
- local wifi_enabled=$(grep -cm1 '^[[:blank:]]*AUTO_SETUP_NET_WIFI_ENABLED=1' /boot/dietpi.txt)
- local use_static=$(grep -cm1 '^[[:blank:]]*AUTO_SETUP_NET_USESTATIC=1' /boot/dietpi.txt)
- local static_ip=$(sed -n '/^[[:blank:]]*AUTO_SETUP_NET_STATIC_IP=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
- local static_mask=$(sed -n '/^[[:blank:]]*AUTO_SETUP_NET_STATIC_MASK=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
- local static_gateway=$(sed -n '/^[[:blank:]]*AUTO_SETUP_NET_STATIC_GATEWAY=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
- local static_dns=$(sed -n '/^[[:blank:]]*AUTO_SETUP_NET_STATIC_DNS=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
-
- # - WiFi
- if (( $wifi_enabled ))
- then
- # Enable WiFi kernel modules
- /boot/dietpi/func/dietpi-set_hardware wifimodules enable
-
- # Apply SSIDs/keys from /boot/dietpi-wifi.txt to /etc/wpa_supplicant/wpa_supplicant.conf
- /boot/dietpi/func/dietpi-wifidb 1
-
- # Apply WiFi country code from /boot/dietpi.txt
- /boot/dietpi/func/dietpi-set_hardware wificountrycode
+ # Boot wait for network
+ /boot/dietpi/func/dietpi-set_software boot_wait_for_network "$(( ! $(grep -cm1 '^[[:blank:]]*AUTO_SETUP_BOOT_WAIT_FOR_NETWORK=0' /boot/dietpi.txt) ))"
- # Enable WiFi, disable Ethernet
- ethernet_enabled=0
- sed --follow-symlinks -Ei "/(allow-hotplug|auto)[[:blank:]]+wlan/c\allow-hotplug $iface_wlan" /etc/network/interfaces
- sed --follow-symlinks -Ei "/(allow-hotplug|auto)[[:blank:]]+eth/c\#allow-hotplug $iface_eth" /etc/network/interfaces
+ # IPv6
+ /boot/dietpi/func/dietpi-set_hardware enableipv6 "$(( ! $(grep -cm1 '^[[:blank:]]*CONFIG_ENABLE_IPV6=0' /boot/dietpi.txt) ))"
- # - Ethernet
- elif (( $ethernet_enabled ))
+ # Network interface setup
+ if dpkg-query -s 'ifupdown' 2> /dev/null | grep -q '^Status: install ok installed$'
then
- # Enable Ethernet, disable WiFi
- wifi_enabled=0
- sed --follow-symlinks -Ei "/(allow-hotplug|auto)[[:blank:]]+eth/c\allow-hotplug $iface_eth" /etc/network/interfaces
- sed --follow-symlinks -Ei "/(allow-hotplug|auto)[[:blank:]]+wlan/c\#allow-hotplug $iface_wlan" /etc/network/interfaces
- fi
+ # Apply forced Ethernet link speed if set in dietpi.txt
+ /boot/dietpi/func/dietpi-set_hardware eth-forcespeed "$(sed -n '/^[[:blank:]]*AUTO_SETUP_NET_ETH_FORCE_SPEED=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)"
- # - Static IP
- if (( $use_static ))
- then
- if (( $wifi_enabled ))
+ # Network setup
+ local eth_enabled=$(grep -cm1 '^[[:blank:]]*AUTO_SETUP_NET_ETHERNET_ENABLED=1' /boot/dietpi.txt)
+ local wifi_enabled=$(grep -cm1 '^[[:blank:]]*AUTO_SETUP_NET_WIFI_ENABLED=1' /boot/dietpi.txt)
+ if (( $eth_enabled || $wifi_enabled ))
then
- sed --follow-symlinks -i "/iface wlan/c\iface $iface_wlan inet static" /etc/network/interfaces
+ # Force dietpi-network CLI arguments from user requested settings from dietpi.txt
+ local net_flags=('--enable' '--force' '--no-restart')
+ local use_static=$(grep -cm1 '^[[:blank:]]*AUTO_SETUP_NET_USESTATIC=1' /boot/dietpi.txt)
+ if (( $use_static ))
+ then
+ local static_ip=$(sed -n '/^[[:blank:]]*AUTO_SETUP_NET_STATIC_IP=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
+ local static_gateway=$(sed -n '/^[[:blank:]]*AUTO_SETUP_NET_STATIC_GATEWAY=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
+ local static_dns=$(sed -n '/^[[:blank:]]*AUTO_SETUP_NET_STATIC_DNS=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
+
+ net_flags+=('--static')
+ [[ $static_ip ]] && net_flags+=('--ip' "$static_ip")
+ [[ $static_gateway ]] && net_flags+=('--gateway' "$static_gateway")
+ [[ $static_dns ]] && net_flags+=('--dns' "$static_dns")
+ else
+ net_flags+=('--dhcp')
+ fi
- elif (( $ethernet_enabled ))
- then
- sed --follow-symlinks -i "/iface eth/c\iface $iface_eth inet static" /etc/network/interfaces
- fi
- sed --follow-symlinks -i "/address/c\address $static_ip" /etc/network/interfaces
- sed --follow-symlinks -i "/netmask/c\netmask $static_mask" /etc/network/interfaces
- sed --follow-symlinks -i "/gateway/c\gateway $static_gateway" /etc/network/interfaces
- if command -v resolvconf > /dev/null
- then
- sed --follow-symlinks -i "/dns-nameservers/c\dns-nameservers $static_dns" /etc/network/interfaces
- else
- > /etc/resolv.conf
- for i in $static_dns; do echo "nameserver $i" >> /etc/resolv.conf; done
- sed --follow-symlinks -i "/dns-nameservers/c\#dns-nameservers $static_dns" /etc/network/interfaces
- fi
- fi
+ # Enable WiFi if requested
+ if (( $wifi_enabled ))
+ then
+ # Enable WiFi kernel modules
+ /boot/dietpi/func/dietpi-set_hardware wifimodules enable
- # - IPv6
- /boot/dietpi/func/dietpi-set_hardware enableipv6 "$(( ! $(grep -cm1 '^[[:blank:]]*CONFIG_ENABLE_IPV6=0' /boot/dietpi.txt) ))"
+ # Apply SSIDs/keys from /boot/dietpi-wifi.txt to /etc/wpa_supplicant/wpa_supplicant.conf
+ /boot/dietpi/func/dietpi-wifidb 1
- # - Configure enabled interfaces now, /etc/network/interfaces will be effective from next boot on
- # Failsafe: Bring up Ethernet, whenever WiFi is disabled or fails to be configured, e.g. due to wrong credentials
- # shellcheck disable=SC2015
- (( $wifi_enabled )) && ifup "$iface_wlan" || ifup "$iface_eth"
+ # Apply WiFi country code from /boot/dietpi.txt
+ /boot/dietpi/func/dietpi-set_hardware wificountrycode
- # - Boot wait for network
- /boot/dietpi/func/dietpi-set_software boot_wait_for_network "$(( ! $(grep -cm1 '^[[:blank:]]*AUTO_SETUP_BOOT_WAIT_FOR_NETWORK=0' /boot/dietpi.txt) ))"
+ # Grab available WiFi interface
+ local iface_wifi=$(G_GET_NET -q -t wlan iface)
+ fi
- # Apply network time sync mirror and force sync now to speed up first run setup
- /boot/dietpi/func/dietpi-set_software timesync-mirror
- systemctl restart systemd-timesyncd
+ # Configure and bring up interfaces now, using Ethernet also as fallback if WiFi fails.
+ # - If no interface has been detected yet, configure with wlan0/eth0 names, but do not bring up now.
+ # - This way, ifupdown's udev rules can trigger ifup@.service once the interface is detected.
+ # - Use ifup here, instead of ifup@.service, for easier logging, and to support non-hotplug/auto interfaces.
+ # shellcheck disable=SC2015
+ (( $wifi_enabled )) &&
+ /boot/dietpi/dietpi-network apply "${iface_wifi:-wlan0}" "${net_flags[@]}" &&
+ [[ $iface_wifi ]] && ifup "$iface_wifi" || {
+ local iface_eth=$(G_GET_NET -q -t eth iface)
+ /boot/dietpi/dietpi-network apply "${iface_eth:-eth0}" "${net_flags[@]}" &&
+ [[ $iface_eth ]] && ifup "$iface_eth"
+ }
+ fi
+ fi
- # x86_64 BIOS: Set GRUB install device: https://github.com/MichaIng/DietPi/issues/4542
- if (( $G_HW_ARCH == 10 )) && dpkg-query -s grub-pc &> /dev/null
+ # Apply network time sync mirror and force sync now to speed up first run setup
+ if dpkg-query -s 'systemd-timesyncd' 2> /dev/null | grep -q '^Status: install ok installed$'
then
- local root_drive=$(lsblk -npo PKNAME "$(findmnt -Ufvnro SOURCE /)")
- [[ $root_drive == '/dev/'* ]] && debconf-set-selections <<< "grub-pc grub-pc/install_devices multiselect $root_drive"
+ /boot/dietpi/func/dietpi-set_software timesync-mirror
+ systemctl restart systemd-timesyncd
fi
}