From d1455560ac341ceb81ebd0472b0d4ff7205ec1f2 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 9 Aug 2026 00:31:52 +0200 Subject: [PATCH 01/47] changelog: fix typo --- CHANGELOG.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index f0e4af6eb7..27e6181547 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -8,7 +8,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: From 9b2ce32f9159906cf74558b3d228c7f8b4269c3f Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 10 Aug 2026 01:21:50 +0200 Subject: [PATCH 02/47] dietpi-banner: show also unmouned drives in menu `--fstab` shows only mounts defined in `/etc/fstab`, which however should be fine. The benefit is that it shows also drives which are not currently mounted, or not mounted yet as of `x-systemd.automount`. This also removes the unnecessary `-D` option from the other call. An issue which still needs to be addressed, is to trigger `x-systemd.automount`s before obtaining usage stats. Otherwise no-yet mounted drives from patterns are missing, and explicit selections will show `???` placeholder values. A cheap/efficient but effective method to `test -e` or similar matching mountpoints, before the `findmnt` call, needs to be found. --- dietpi/func/dietpi-banner | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dietpi/func/dietpi-banner b/dietpi/func/dietpi-banner index 0371e39ac9..f21e33745c 100755 --- a/dietpi/func/dietpi-banner +++ b/dietpi/func/dietpi-banner @@ -508,7 +508,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 +653,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[@]}" From e231129f99a38d6c6a4ec4b8c9024f27f42708b2 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 10 Aug 2026 01:31:50 +0200 Subject: [PATCH 03/47] Raspberry Pi: blocks cups-filters from RPi repo It is compiled against qpdf from Raspbian, which seems to be ABI-incompatible with the one from Debian. The only RPi repo patch is preventing the `cups-browsed` service from the same-named package from being enabled and started on package install. Something which is not relevant for DietPi. --- .build/images/dietpi-installer | 3 ++- .update/pre-patches | 25 +++++++++++++++++-------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/.build/images/dietpi-installer b/.build/images/dietpi-installer index fa8757ec49..d596286d46 100755 --- a/.build/images/dietpi-installer +++ b/.build/images/dietpi-installer @@ -957,8 +957,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_' 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 } From 3a86ac1c5323406ec877615050950df3e1d29d2b Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 10 Aug 2026 14:20:49 +0200 Subject: [PATCH 04/47] dietpi-build: raise RISC-V Forky rootfs size 425 MiB only for WiFi firmware now, 70% of the overall disk usage, vs 303 MiB on Trixie ... I think we should switch to armbian-firmware, where our (reduced) builds are only 145 MiB, a much more selective set of firmware needed for onboard chips, M.2 modules, and USB dongles used on SBCs. --- .build/images/dietpi-build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.build/images/dietpi-build b/.build/images/dietpi-build index 4d36267955..03659c306f 100755 --- a/.build/images/dietpi-build +++ b/.build/images/dietpi-build @@ -186,7 +186,7 @@ case $HW_MODEL in esac case $root_size in 'sun60iw2') root_size=600;; - 'riscv') root_size=650; (( $DISTRO > 8 )) && ((root_size+=100));; + 'riscv') root_size=650; (( $DISTRO > 8 )) && ((root_size+=150));; 'meson') root_size=650; (( $DISTRO > 7 && ! $boot_size )) && ((root_size+=50));; 'rockchip') root_size=700;; 'quartz64') root_size=700; (( $DISTRO > 8 )) && ((root_size+=100));; From e425c6daf8050da27c845d9fc6132197af4c4472 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 10 Aug 2026 22:58:43 +0200 Subject: [PATCH 05/47] dietpi-trixie-upgrade: migrate OpenSSH setting more aggressively ChallengeResponseAuthentication appears as well in several comment lines. Just replace any occurance with KbdInteractiveAuthentication, to avoid confusion. Duplicates wouldn't cause issues either. Other thing: Recognise the Raspberry Pi Compute Modul Zero. It uses the BCM2710 SoC, and has optional onboard WiFi. Need to check for other compute modules, whether we should set G_HW_ONBOARD_WIFI=1 there as well, so that onboard WiFi can be properly toggled, if present. Need to check as well whether it causes any issue, if onboard WiFi absent. --- .meta/dietpi-bookworm-upgrade | 6 +++++- dietpi/func/dietpi-obtain_hw_model | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) 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/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 From eb769e1e9155b7ed56e1356de23cb0f6823511f9 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Tue, 11 Aug 2026 21:05:59 +0200 Subject: [PATCH 06/47] dietpi-software: Chromium: update flags Apply also retrospectively, since "--no-sandbox" has security impacts, should hence not be used if it is not really the root user explicitly starting Chromium. --- .update/patches | 14 ++++++++++++++ dietpi/dietpi-software | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.update/patches b/.update/patches index 7b67fdc53b..ed69aef860 100755 --- a/.update/patches +++ b/.update/patches @@ -2580,7 +2580,21 @@ 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. + G_EXEC eval 'echo '\''[ "$(id -u)" -eq 0 ] && export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --no-sandbox --test-type"'\'' > /etc/chromium.d/dietpi' + fi + + # 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/dietpi/dietpi-software b/dietpi/dietpi-software index 5ef7dc41ce..934405462a 100755 --- a/dietpi/dietpi-software +++ b/dietpi/dietpi-software @@ -8986,8 +8986,8 @@ 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) + 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 From 059d2289d9a9b10617e4b49f78f074915dc7aaad Mon Sep 17 00:00:00 2001 From: MichaIng Date: Tue, 11 Aug 2026 21:32:17 +0200 Subject: [PATCH 07/47] coding: mute shellcheck --- .update/patches | 1 + dietpi/dietpi-software | 1 + 2 files changed, 2 insertions(+) diff --git a/.update/patches b/.update/patches index ed69aef860..d6dafd26cb 100755 --- a/.update/patches +++ b/.update/patches @@ -2589,6 +2589,7 @@ Patch_10_7() 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 diff --git a/dietpi/dietpi-software b/dietpi/dietpi-software index 934405462a..ded22cfd45 100755 --- a/dietpi/dietpi-software +++ b/dietpi/dietpi-software @@ -8987,6 +8987,7 @@ sudo sysctl -p /etc/sysctl.d/dietpi-syncthing.confs (( $G_HW_MODEL > 9 )) || /boot/dietpi/func/dietpi-set_hardware rpi-codec 1 # 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 From ca0c946cd613d7daddf17e03f3df28106cb0884d Mon Sep 17 00:00:00 2001 From: MichaIng Date: Tue, 11 Aug 2026 21:35:18 +0200 Subject: [PATCH 08/47] dietpi-patches: remove obsolete patch superseded in v10.7 --- .update/patches | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.update/patches b/.update/patches index d6dafd26cb..4ad206048c 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() From 7a57783c02562d5f8858ae20a1c7bfe1f789a4fc Mon Sep 17 00:00:00 2001 From: MichaIng Date: Wed, 12 Aug 2026 12:52:26 +0200 Subject: [PATCH 09/47] ci: update_urls: print checked ID before network request --- .github/workflows/update_urls.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update_urls.bash b/.github/workflows/update_urls.bash index 083df32d81..a559ef7e5e 100644 --- a/.github/workflows/update_urls.bash +++ b/.github/workflows/update_urls.bash @@ -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 From 766532fdf72609cd79fe3eebfa0e71b87ee6a3d5 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Wed, 12 Aug 2026 13:05:51 +0200 Subject: [PATCH 10/47] dietpi-software: Ampache: fix version check after v8 release --- .github/workflows/update_urls.bash | 2 +- CHANGELOG.txt | 14 ++++++++++++++ dietpi/dietpi-software | 4 +++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/update_urls.bash b/.github/workflows/update_urls.bash index a559ef7e5e..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}' diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 27e6181547..d35634c615 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,17 @@ +v10.6 +(2026-09-05) + +New images: + +Enhancements: + +Bug fixes: +- 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) diff --git a/dietpi/dietpi-software b/dietpi/dietpi-software index ded22cfd45..c56e0563ea 100755 --- a/dietpi/dietpi-software +++ b/dietpi/dietpi-software @@ -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/ From fcbe8ddf4df2456f6584c7f9a13ea354de760648 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Wed, 12 Aug 2026 13:06:12 +0200 Subject: [PATCH 11/47] changelog: typo --- CHANGELOG.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d35634c615..1cb7e73bb7 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,4 +1,4 @@ -v10.6 +v10.7 (2026-09-05) New images: From bea3d1e72223c9566e8a0374b803462f01f6f47e Mon Sep 17 00:00:00 2001 From: MichaIng Date: Thu, 13 Aug 2026 14:32:24 +0200 Subject: [PATCH 12/47] coding: shorten some "date" call formats Also, the VirtualBox OVF did use %M where %m was intended, causing unintended and potentially invalid last state change timestamps (with however no real practical issues). --- .build/images/dietpi-build | 2 +- .meta/dietpi-survey_report | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.build/images/dietpi-build b/.build/images/dietpi-build index 03659c306f..94392f8ac8 100755 --- a/.build/images/dietpi-build +++ b/.build/images/dietpi-build @@ -1045,7 +1045,7 @@ then 10 - + Complete VirtualBox machine configuration in VirtualBox format diff --git a/.meta/dietpi-survey_report b/.meta/dietpi-survey_report index 3c55df0c47..5757e773c3 100755 --- a/.meta/dietpi-survey_report +++ b/.meta/dietpi-survey_report @@ -1116,7 +1116,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.

From bf553e37c186f0dba740a3cc12c1f156c65e0208 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 13 Aug 2026 14:50:05 +0200 Subject: [PATCH 13/47] Extend regex in dietpi-banner to also count bans created in CIDR notation (#8248) and adjust ban messages accordingly ("IPs" => "bans") --- CHANGELOG.txt | 1 + dietpi/func/dietpi-banner | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 1cb7e73bb7..9527c660fd 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,7 @@ v10.7 New images: 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)". Bug fixes: - 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. diff --git a/dietpi/func/dietpi-banner b/dietpi/func/dietpi-banner index f21e33745c..8937279442 100755 --- a/dietpi/func/dietpi-banner +++ b/dietpi/func/dietpi-banner @@ -352,7 +352,7 @@ $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:]*)$' + local IP_re='^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[0-9a-f:]*:[0-9a-f:]*)(/[0-9]+)?$' if [[ $EUID == 0 ]] then fail2ban-client banned 2> /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";; From e16d15af31b8da043dfa65832a578f9222aa3918 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 15 Aug 2026 01:03:38 +0200 Subject: [PATCH 14/47] dietpi-banner: some fixes * Correctly catch sudo error in Fail2Ban status, via PIPESTATUS[0], otherwise the exit code of "mawk" is checked. * Use sudo as well for systemd status as non-root, if dbus is not active, needed for non-root users to call systemctl. --- dietpi/func/dietpi-banner | 40 ++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/dietpi/func/dietpi-banner b/dietpi/func/dietpi-banner index 8937279442..5640680c24 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 <<< $failed_cnt + + if (( ${#failed_cnt[@]} )) + then + echo "${aCOLOUR[alert]}${#failed_cnt[@]} service(s) failed" + else + echo 'No services failed' fi } @@ -353,11 +366,12 @@ $CLI_LINE" 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:]*)(/[0-9]+)?$' - if [[ $EUID == 0 ]] + 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 Date: Sat, 15 Aug 2026 01:12:42 +0200 Subject: [PATCH 15/47] coding: satisfy shellcheck --- dietpi/func/dietpi-banner | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dietpi/func/dietpi-banner b/dietpi/func/dietpi-banner index 5640680c24..c44df0bdb0 100755 --- a/dietpi/func/dietpi-banner +++ b/dietpi/func/dietpi-banner @@ -348,7 +348,7 @@ $CLI_LINE" fi fi - mapfile -t failed_cnt <<< $failed_cnt + mapfile -t failed_cnt <<< "$failed_cnt" if (( ${#failed_cnt[@]} )) then From 0536aa3c9bd84e07f198e17767e06c590142dadd Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 15 Aug 2026 13:22:31 +0200 Subject: [PATCH 16/47] dietpi-software: Kodi: do not raise CMA size on RPi 5 According to an RPi engineer, this is not needed on RPi 5 anymore for proper 4k support. dietpi-globals: fix comment typo and print error to STDERR --- dietpi/dietpi-software | 4 ++-- rootfs/etc/bashrc.d/dietpi.bash | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dietpi/dietpi-software b/dietpi/dietpi-software index c56e0563ea..4f86c61af7 100755 --- a/dietpi/dietpi-software +++ b/dietpi/dietpi-software @@ -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 diff --git a/rootfs/etc/bashrc.d/dietpi.bash b/rootfs/etc/bashrc.d/dietpi.bash index 64f856a08f..1f3a9277bd 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 @@ -61,7 +61,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 From bbec5f028673f7efc22199e06850819ba0bfde41 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 15 Aug 2026 14:46:00 +0200 Subject: [PATCH 17/47] Raspberry Pi: fix dtparam/dtoverlay ordering --- .build/images/RPi/config.txt | 8 ++++---- .build/images/dietpi-installer | 8 +++++++- .update/patches | 8 ++++++++ CHANGELOG.txt | 1 + 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/.build/images/RPi/config.txt b/.build/images/RPi/config.txt index 18cb747559..cee4327f9d 100644 --- a/.build/images/RPi/config.txt +++ b/.build/images/RPi/config.txt @@ -39,10 +39,6 @@ disable_overscan=1 # LCD/OLED Rotation #lcd_rotate=0 -# Enable KMS/DRM display driver, recommended when a GUI application or desktop is used. -# Remove ",noaudio" if HDMI audio is needed, or enable it via dietpi-config. -#dtoverlay=vc4-kms-v3d,noaudio - #-------RPi camera module------- #camera_auto_detect=1 #disable_camera_led=1 @@ -87,3 +83,7 @@ initial_turbo=20 #arm_freq_min=300 #core_freq_min=250 #sdram_freq_min=400 + +# Enable KMS/DRM display driver, recommended when a GUI application or desktop is used. +# Remove ",noaudio" if HDMI audio is needed, or enable it via dietpi-config. +#dtoverlay=vc4-kms-v3d,noaudio diff --git a/.build/images/dietpi-installer b/.build/images/dietpi-installer index d596286d46..1dcf2b040d 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 diff --git a/.update/patches b/.update/patches index 4ad206048c..31d4fecce5 100755 --- a/.update/patches +++ b/.update/patches @@ -2582,6 +2582,14 @@ Patch_10_7() 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' + 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 + # Software updates, migrations and patches if [[ -f '/boot/dietpi/.installed' ]] then diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 9527c660fd..0277dda68c 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -7,6 +7,7 @@ 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)". 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 - 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 From 2d823acc7258e5b8008e4218c1844995d256cc51 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 15 Aug 2026 14:53:02 +0200 Subject: [PATCH 18/47] coding: mute shellcheck false positive --- .update/patches | 1 + 1 file changed, 1 insertion(+) diff --git a/.update/patches b/.update/patches index 31d4fecce5..d9a0c4875a 100755 --- a/.update/patches +++ b/.update/patches @@ -2586,6 +2586,7 @@ Patch_10_7() 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 From 4006a9280dfdc8e11d631f7bf43f7e9a44532037 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 15 Aug 2026 15:39:43 +0200 Subject: [PATCH 19/47] ci: dietpi-build: attempt to fix service order Our dietpi-build.service controlling terminal is sometimes stolen by console-getty.service, which is Type=idle as well, causing an immediate shutdown. If ordering works between Type=idle services, and console-getty (which is Before=getty.target > multi-user.target > graphical.target) claims /dev/console before follow-up targets are reached, this should reliably solve the issue. Otherwise a mask, as used before the general /dev/console issue on QEMU-emulated Forky systems was solved, solves it reliably. But late ordering of our service makes sense anyway to avoid mixing outputs etc, and we want to keep interference minimal. --- .build/images/dietpi-build | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.build/images/dietpi-build b/.build/images/dietpi-build index 94392f8ac8..6d2b38dd2b 100755 --- a/.build/images/dietpi-build +++ b/.build/images/dietpi-build @@ -495,6 +495,9 @@ exit 0 _EOF_ G_EXEC chmod +x rootfs/dietpi-build.sh cat << '_EOF_' > rootfs/etc/systemd/system/dietpi-build.service || exit 1 +[Unit] +After=graphical.target + [Service] Type=idle StandardOutput=tty From be7fe69c9dad7ec042c471c04b760465f2985197 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 15 Aug 2026 18:10:40 +0200 Subject: [PATCH 20/47] dietpi-banner: print (update) notifications below dietpi-* commands It seems the more natural order, with the more important notifications right above the command prompt. --- dietpi/func/dietpi-banner | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dietpi/func/dietpi-banner b/dietpi/func/dietpi-banner index c44df0bdb0..b1bada93e1 100755 --- a/dietpi/func/dietpi-banner +++ b/dietpi/func/dietpi-banner @@ -1039,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() From 371b7bd9080a048133cf9a741404a0767e9af9bb Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 15 Aug 2026 19:49:06 +0200 Subject: [PATCH 21/47] dietpi-build: switch to After=multi-user.target Otherwise systemd somehow seems an ordering cycle between dietpi-build.service, graphical.target, and multi-user.target. It seems, since the service is pulled in by multi-user.target (`/etc/systemd/system/multi-user.target.wants/dietpi-build.service`), this implies Before=multi-user.target, or so. Anyway, there is nothing between those two targets on a fresh Debian, hence it shouldn't make a difference. The `/etc/systemd/system/graphical.target.wants` dir does not exist OOTB, and we want to add as few stuff as possible. --- .build/images/dietpi-build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.build/images/dietpi-build b/.build/images/dietpi-build index 6d2b38dd2b..6c4b295572 100755 --- a/.build/images/dietpi-build +++ b/.build/images/dietpi-build @@ -496,7 +496,7 @@ _EOF_ G_EXEC chmod +x rootfs/dietpi-build.sh cat << '_EOF_' > rootfs/etc/systemd/system/dietpi-build.service || exit 1 [Unit] -After=graphical.target +After=multi-user.target [Service] Type=idle @@ -504,7 +504,7 @@ StandardOutput=tty ExecStart=-/dietpi-build.sh ExecStopPost=/usr/bin/systemctl --no-block start poweroff.target _EOF_ -G_EXEC ln -s /etc/systemd/system/dietpi-build.service rootfs/etc/systemd/system/multi-user.target.wants/dietpi-build.service +G_EXEC ln -s ../dietpi-build.service rootfs/etc/systemd/system/multi-user.target.wants/dietpi-build.service # Start container # - Bind mounts required to allow container reading its own drive info, /dev/disk for GRUB and probably other tools to detect UUIDs From 71ad2cce645fc43636c25b0123aa4d199e89ce6a Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 15 Aug 2026 20:11:31 +0200 Subject: [PATCH 22/47] dietpi-build: mask console-getty.service Even when starting earlier, console-getty.service can take longer for the login prompt, after dietpi-build.service started, stealing its controlling terminal. Hence there is no way around masking it. The After=multi-user.target still makes sense for a cleaner output ordering. Also, disable wpa_supplicant.service before booting, as it is doomed to fail, causing an ugly failure log, and is otherwise disabled by dietpi-installer anyway. --- .build/images/dietpi-build | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.build/images/dietpi-build b/.build/images/dietpi-build index 6c4b295572..82672693d8 100755 --- a/.build/images/dietpi-build +++ b/.build/images/dietpi-build @@ -441,9 +441,11 @@ G_EXEC mount -m -t tmpfs tmpfs rootfs/run G_EXEC mount -m -t tmpfs tmpfs rootfs/var/cache/apt G_EXEC mount -m -t tmpfs tmpfs rootfs/var/lib/apt/lists G_EXEC mount -m -t tmpfs tmpfs rootfs/var/log -# - "--skip=check/empty" to ignore /etc/fstab, boot and tmpfs mounts we added above -# - "--skip=check/qemu" to skip arch test, which requires the "arch-test" package. We however assure emulation support our end. +# "--skip=check/empty" to ignore /etc/fstab, boot and tmpfs mounts we added above +# "--skip=check/qemu" to skip arch test, which requires the "arch-test" package. We however assure emulation support our end. G_EXEC_OUTPUT=1 G_EXEC mmdebstrap --mode=root --format=dir --skip=check/empty,check/qemu --variant=apt --include="$packages" --arch="$parch" --keyring="$keyring" "$distro" ./rootfs "${mirrors[@]}" +# Prevent doomed wpa_supplicant.service start attempt +[[ $HW_MODEL =~ ^(20|75)$ ]] || G_EXEC systemctl --root=rootfs disable wpa_supplicant G_EXEC umount rootfs/dev rootfs/run rootfs/var/cache/apt rootfs/var/lib/apt/lists rootfs/var/log ########################################## @@ -481,6 +483,8 @@ fi ########################################## # Create boot script and systemd unit to automate DietPi-Installer # - NB: WIFI_REQUIRED=1 is always passed here, but ignored by DietPi-Installer for VMs and containers. +# - Prevent console-getty.service from stealing the controlling terminal +G_EXEC ln -s /dev/null rootfs/etc/systemd/system/console-getty.service cat << _EOF_ > rootfs/dietpi-build.sh || exit 1 #!/bin/dash -e { @@ -488,7 +492,7 @@ infocmp "\$TERM" > /dev/null 2>&1 || { echo "[ WARN ] Unsupported TERM=\"\$TERM\ export GITOWNER='$GITOWNER' GITBRANCH='$GITBRANCH' HW_MODEL='$HW_MODEL' IMAGE_CREATOR=0 PREIMAGE_INFO=0 WIFI_REQUIRED=1 DISTRO_TARGET=$DISTRO TEST_KERNEL=$TEST_KERNEL TEST_UBOOT=$TEST_UBOOT RK35XX_MAINLINE=$RK35XX_MAINLINE TMPDIR='/tmp' echo '[ INFO ] Running DietPi-Installer for $G_GITOWNER/$G_GITBRANCH' bash -c "\$(curl -sSf 'https://raw.githubusercontent.com/$G_GITOWNER/DietPi/$G_GITBRANCH/.build/images/dietpi-installer' || echo false)" || { echo '[FAILED] DietPi-Installer failed, shutting down ...'; journalctl -n 25; df -h; free -h; exit 1; } -rm -v /etc/systemd/system/multi-user.target.wants/dietpi-build.service /etc/systemd/system/dietpi-build.service /dietpi-build.sh +rm -v /etc/systemd/system/multi-user.target.wants/dietpi-build.service /etc/systemd/system/dietpi-build.service /dietpi-build.sh /etc/systemd/system/console-getty.service > /success exit 0 } From b2b97f0cb04ab0238045ae6627ed1a1b0e569885 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 15 Aug 2026 21:57:57 +0200 Subject: [PATCH 23/47] dietpi-build: remove conditional for _mailine suffix The additional ID list here has been forgotten, and the NanoPi Zero2 (ID 104) mainline Linux builds were overriding the vendor Linux builds, due to the missing suffix. The conditional here is redundant. Our CI uses the "--rk35xx-mainline" flag only where it actually expects a dedicated image. --- .build/images/dietpi-build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.build/images/dietpi-build b/.build/images/dietpi-build index 82672693d8..bbc4bb7cdb 100755 --- a/.build/images/dietpi-build +++ b/.build/images/dietpi-build @@ -247,7 +247,7 @@ G_CHECK_URL "https://github.com/$GITOWNER/DietPi/tree/$GITBRANCH" || Error_Exit # Generate image name and define CLONING_TOOL for dietpi-installer OUTPUT_IMG_NAME="DietPi_$iname-$iarch-${distro^}" -[[ $RK35XX_MAINLINE == 1 && $HW_MODEL =~ ^(78|79'.'[1-3]|80|82|85|90|91|92|93|94|95|102|103)$ ]] && OUTPUT_IMG_NAME+='_mainline' +[[ $RK35XX_MAINLINE == 1 ]] && OUTPUT_IMG_NAME+='_mainline' [[ $fsname ]] && OUTPUT_IMG_NAME+="_$fsname" CLONING_TOOL='dd' if [[ $VARIANT == 'iso' ]] From 722364d5180abdcee81fa3a8ad5533b0666b80ba Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 15 Aug 2026 22:14:17 +0200 Subject: [PATCH 24/47] dietpi-build: adjust rootfs size for rk35xx => mainline builds --- .build/images/dietpi-build | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.build/images/dietpi-build b/.build/images/dietpi-build index bbc4bb7cdb..e0f9e19fb7 100755 --- a/.build/images/dietpi-build +++ b/.build/images/dietpi-build @@ -184,6 +184,7 @@ case $HW_MODEL in 108) iname='OrangePiZero3W' HW_ARCH=3 partition_start=32 root_size='sun60iw2';; *) Error_Exit "Invalid hardware model \"$HW_MODEL\" passed";; esac +[[ $root_size == 'rk35xx' && $RK35XX_MAINLINE == 1 ]] && root_size='rockchip64' case $root_size in 'sun60iw2') root_size=600;; 'riscv') root_size=650; (( $DISTRO > 8 )) && ((root_size+=150));; @@ -247,7 +248,7 @@ G_CHECK_URL "https://github.com/$GITOWNER/DietPi/tree/$GITBRANCH" || Error_Exit # Generate image name and define CLONING_TOOL for dietpi-installer OUTPUT_IMG_NAME="DietPi_$iname-$iarch-${distro^}" -[[ $RK35XX_MAINLINE == 1 ]] && OUTPUT_IMG_NAME+='_mainline' +(( $RK35XX_MAINLINE )) && OUTPUT_IMG_NAME+='_mainline' [[ $fsname ]] && OUTPUT_IMG_NAME+="_$fsname" CLONING_TOOL='dd' if [[ $VARIANT == 'iso' ]] From 6c08a15437a279096113017d0a81cdcdfad473d4 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 16 Aug 2026 14:12:45 +0200 Subject: [PATCH 25/47] dietpi-software: Nextcloud: add GMP PHP module The notifications app (a vendored dependency of it) started to throw an info log message whenever it is called, that it "strongly recommends" GMP or BCMath for better performance. GMP is needed for the SFTP storage backend as well, and recommended when using WebAuthn authentication. And it seems to perform better. So we're going with that one. --- .build/images/RPi/config.txt | 2 +- dietpi/dietpi-software | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.build/images/RPi/config.txt b/.build/images/RPi/config.txt index cee4327f9d..de3781281a 100644 --- a/.build/images/RPi/config.txt +++ b/.build/images/RPi/config.txt @@ -16,7 +16,7 @@ # Uncomment to disable HDMI even if plugged, e.g. to force composite output. #hdmi_ignore_hotplug=1 -# Uncomment to enable SDTV/composite output from RPi4 on. This has no effect on previous RPi models. +# Uncomment to enable SDTV/composite output from RPi4 on. This has no effect on older RPi models. #enable_tvout=1 # Uncomment to force an HDMI mode rather than DVI. This enables HDMI audio in DMT modes. diff --git a/dietpi/dietpi-software b/dietpi/dietpi-software index 4f86c61af7..c3560f70f0 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") From a0b4f24b402a85be54ef6f9c42e7c9ce3c365738 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 17 Aug 2026 13:15:18 +0200 Subject: [PATCH 26/47] dietpi-installer: Orange Pi 5/5B: enable vertical USB 2.0 port The overlay name which sets it to host mode is different in mainline Linux. --- .build/images/dietpi-installer | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.build/images/dietpi-installer b/.build/images/dietpi-installer index 1dcf2b040d..5f23861b87 100755 --- a/.build/images/dietpi-installer +++ b/.build/images/dietpi-installer @@ -771,7 +771,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 From a27cd0847c7d94ebdf99117e8b7903ba59b6bdcb Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 17 Aug 2026 13:34:51 +0200 Subject: [PATCH 27/47] Init v10.7 --- .meta/dietpi-survey_report | 2 ++ .update/version | 4 ++-- dietpi/func/dietpi-globals | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.meta/dietpi-survey_report b/.meta/dietpi-survey_report index 5757e773c3..53b7f4d8a0 100755 --- a/.meta/dietpi-survey_report +++ b/.meta/dietpi-survey_report @@ -628,11 +628,13 @@ 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 diff --git a/.update/version b/.update/version index 4808f2cdfe..8d16d008b3 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=-1 # Minimum DietPi version to allow update G_MIN_VERSION_CORE=8 G_MIN_VERSION_SUB=0 diff --git a/dietpi/func/dietpi-globals b/dietpi/func/dietpi-globals index c42ca6b362..7391c4b0c4 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=-1 [[ $G_GITBRANCH ]] || G_GITBRANCH='master' [[ $G_GITOWNER ]] || G_GITOWNER='MichaIng' # - Save current version and Git branch From d4bc41238631c8de311e794271350264e9f68414 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 17 Aug 2026 13:59:32 +0200 Subject: [PATCH 28/47] dietpi-survey_report: fix final version loop --- .meta/dietpi-survey_report | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.meta/dietpi-survey_report b/.meta/dietpi-survey_report index 53b7f4d8a0..0d8d004d1b 100755 --- a/.meta/dietpi-survey_report +++ b/.meta/dietpi-survey_report @@ -638,7 +638,7 @@ shopt -s extglob # +(expr) syntax 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 From ce7ca65a65441a9694629178a38373a0eaa970a7 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 17 Aug 2026 23:05:50 +0200 Subject: [PATCH 29/47] dietpi-trixie-upgrade: fix migration of RPi Kodi 20 package The Kodi 20 package from the RPi Bookworm repo have a different file distribution between kodi and kodi-bin, which causes a conflict when dpkg tries to unpack files of the new kodi-bin package while the old kodi package is still installed. Purge it first, leaving dependencies in place, and let `apt-get dist-upgrade` reinstall it along with the other upgrades. --- .meta/dietpi-trixie-upgrade | 7 +++++++ 1 file changed, 7 insertions(+) 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 From 145fb9c1f7c89976b64550be8219b62e72e84401 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Wed, 19 Aug 2026 12:52:47 +0200 Subject: [PATCH 30/47] Radxa ZERO 3: add overlay prefix for external antenna overlay --- .build/images/dietpi-installer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.build/images/dietpi-installer b/.build/images/dietpi-installer index 5f23861b87..60b5a4c87e 100755 --- a/.build/images/dietpi-installer +++ b/.build/images/dietpi-installer @@ -756,7 +756,7 @@ setenv bootlabel "DietPi"' /boot/boot.cmd 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;; From a41995cee9ba77c6dbda17fc1dfed6fb4bcdaeb7 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Fri, 21 Aug 2026 16:10:45 +0200 Subject: [PATCH 31/47] ci: armbian: add support for sun60iw2 kernel build --- .github/workflows/armbian.yml | 1 + 1 file changed, 1 insertion(+) 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" From b1077ea3b81a8044afa2a11fff5f3ad0e5d5dd40 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Fri, 21 Aug 2026 20:52:05 +0200 Subject: [PATCH 32/47] dietpi-drive_manager: align variable name This is for Btrfs, not F2FS --- dietpi/dietpi-drive_manager | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 From 57a40cf47a7ed6ea3aaf1a1a3e4978605d5537a6 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Fri, 21 Aug 2026 22:31:20 +0200 Subject: [PATCH 33/47] dietpi-banner: correctly count zero failed systemd services The here string adds a trailing newline to empty variables. Use a process substitution with `echo -n`, to prevent a trailing newline. --- dietpi/func/dietpi-banner | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dietpi/func/dietpi-banner b/dietpi/func/dietpi-banner index b1bada93e1..f6339cb699 100755 --- a/dietpi/func/dietpi-banner +++ b/dietpi/func/dietpi-banner @@ -348,7 +348,7 @@ $CLI_LINE" fi fi - mapfile -t failed_cnt <<< "$failed_cnt" + mapfile -t failed_cnt < <(echo -n "$failed_cnt") if (( ${#failed_cnt[@]} )) then From 243a2b80f38290c40bd94ef915436b4897220c7d Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 22 Aug 2026 15:03:41 +0200 Subject: [PATCH 34/47] ci: dietpi-build software: switch to process substitution --- .github/workflows/dietpi-software-build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/dietpi-software-build.yml b/.github/workflows/dietpi-software-build.yml index 7ab4f61d2d..dabb7ef71a 100644 --- a/.github/workflows/dietpi-software-build.yml +++ b/.github/workflows/dietpi-software-build.yml @@ -79,10 +79,10 @@ jobs: - 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 + #mkdir ~/.ssh + #umask 377 + #echo '${{ secrets.KNOWN_HOSTS }}' > ~/.ssh/known_hosts + #echo '${{ secrets.SSH_KEY }}' > ~/.ssh/id_ed25519 # Generate file lists files= @@ -97,5 +97,5 @@ jobs: echo "Uploading file(s) $files to URL(s) $urls ..." # Upload - curl -T "{$files}" --key ~/.ssh/id_ed25519 '${{ secrets.UPLOAD_URL }}${{ matrix.dist }}/' + curl -T "{$files}" --knownhosts <(echo '${{ secrets.KNOWN_HOSTS }}') --key <(echo '${{ secrets.SSH_KEY }}') '${{ secrets.UPLOAD_URL }}${{ matrix.dist }}/' 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]}" From 7e497269e3b8bc4739acfabe048870d82846f640 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 22 Aug 2026 15:19:39 +0200 Subject: [PATCH 35/47] ci: dietpi-software build: fix syntax --- .github/workflows/dietpi-software-build.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/dietpi-software-build.yml b/.github/workflows/dietpi-software-build.yml index dabb7ef71a..06b16af2c1 100644 --- a/.github/workflows/dietpi-software-build.yml +++ b/.github/workflows/dietpi-software-build.yml @@ -78,12 +78,6 @@ jobs: 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/"' From 922969b801b5fb7da8dd963910b1b073eeddcaab Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 22 Aug 2026 15:34:12 +0200 Subject: [PATCH 36/47] ci: dietpi-software build: switch to Ubuntu 26.04 runners curl received the --knownhosts option with v8.17. --- .build/software/dietpi-software-build.bash | 2 +- .github/workflows/dietpi-software-build.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.build/software/dietpi-software-build.bash b/.build/software/dietpi-software-build.bash index 5d19d92d0a..45f91c2124 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--)) diff --git a/.github/workflows/dietpi-software-build.yml b/.github/workflows/dietpi-software-build.yml index 06b16af2c1..4db09b79be 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,7 +72,7 @@ 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 }}' From c08bf65fa8344183ce7b458fe6d3428d1fb651c5 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 22 Aug 2026 16:05:51 +0200 Subject: [PATCH 37/47] ci: dietpi-software build: revert to files on disk The SSH library cannot parse a key passed via process substitution to curl. At least assure they exist as short as possible. --- .github/workflows/dietpi-software-build.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dietpi-software-build.yml b/.github/workflows/dietpi-software-build.yml index 4db09b79be..9a3897c3cf 100644 --- a/.github/workflows/dietpi-software-build.yml +++ b/.github/workflows/dietpi-software-build.yml @@ -88,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 - curl -T "{$files}" --knownhosts <(echo '${{ secrets.KNOWN_HOSTS }}') --key <(echo '${{ secrets.SSH_KEY }}') '${{ secrets.UPLOAD_URL }}${{ matrix.dist }}/' + 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]}" From d52164f8c3633b862ce5efa1b49662f301471316 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 22 Aug 2026 16:12:41 +0200 Subject: [PATCH 38/47] ci: dietpi-software build: switch to qemu-user-binfmt from Trixie on --- .build/software/dietpi-software-build.bash | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.build/software/dietpi-software-build.bash b/.build/software/dietpi-software-build.bash index 45f91c2124..e222db4fc2 100644 --- a/.build/software/dietpi-software-build.bash +++ b/.build/software/dietpi-software-build.bash @@ -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[@]}" From 91a7d1287b4a62936332201f1d5af9c9d8c8577c Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sat, 22 Aug 2026 23:24:32 +0200 Subject: [PATCH 39/47] rk3399: narrow overlay prefix All overlays for these do now have a specific prefix. Also switch to Ubuntu 26.04 GitHub runners for Quartz64 kernel builds. --- .build/images/dietpi-installer | 3 ++- .github/workflows/quartz64.yml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.build/images/dietpi-installer b/.build/images/dietpi-installer index 60b5a4c87e..10d69c7808 100755 --- a/.build/images/dietpi-installer +++ b/.build/images/dietpi-installer @@ -750,7 +750,6 @@ 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;; @@ -761,7 +760,9 @@ setenv bootlabel "DietPi"' /boot/boot.cmd 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 diff --git a/.github/workflows/quartz64.yml b/.github/workflows/quartz64.yml index 96f7dcefdf..3c33371ae1 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) From 8a3a5da156a34b0f96eed75acead8497b1d153c8 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 23 Aug 2026 00:11:26 +0200 Subject: [PATCH 40/47] ci: quartz64: cleanup right after upload --- .github/workflows/quartz64.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/quartz64.yml b/.github/workflows/quartz64.yml index 3c33371ae1..7b73e4cbc3 100644 --- a/.github/workflows/quartz64.yml +++ b/.github/workflows/quartz64.yml @@ -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"]}' From aff4c9976b94f2d2d598516ab24110d54c364adf Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sun, 23 Aug 2026 21:28:46 +0200 Subject: [PATCH 41/47] dietpi-network: new tool for multi interface configuration (#8251) * Extract network options from diepti-config into own dietpi-network script with per-interface menus and CLI * Support non-classic interface names * Make use of the new CLI across other DietPi scripts Signed-off-by: MichaIng --- .build/images/dietpi-installer | 21 +- .update/patches | 3 + CHANGELOG.txt | 3 + dietpi.txt | 5 +- dietpi/dietpi-config | 1204 +-------------- dietpi/dietpi-login | 2 +- dietpi/dietpi-network | 1322 +++++++++++++++++ dietpi/dietpi-software | 149 +- dietpi/func/dietpi-banner | 2 +- dietpi/func/dietpi-globals | 33 +- dietpi/func/dietpi-set_hardware | 39 +- dietpi/func/dietpi-set_software | 51 +- dietpi/func/dietpi-wifidb | 32 +- rootfs/etc/bashrc.d/dietpi.bash | 1 + .../lib/dietpi/services/dietpi-firstboot.bash | 180 ++- 15 files changed, 1534 insertions(+), 1513 deletions(-) create mode 100755 dietpi/dietpi-network diff --git a/.build/images/dietpi-installer b/.build/images/dietpi-installer index 10d69c7808..f1f0d781fc 100755 --- a/.build/images/dietpi-installer +++ b/.build/images/dietpi-installer @@ -1956,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/.update/patches b/.update/patches index d9a0c4875a..4e6b3eeb5e 100755 --- a/.update/patches +++ b/.update/patches @@ -2591,6 +2591,9 @@ Patch_10_7() 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 diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 0277dda68c..9d041a0901 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -3,6 +3,9 @@ v10.7 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)". 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-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..45564fad9c --- /dev/null +++ b/dietpi/dietpi-network @@ -0,0 +1,1322 @@ +#!/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' ': Do not bring up interface at boot') + else + G_WHIP_MENU_ARRAY+=('Enable' ': Bring up interface at boot') + fi + G_WHIP_MENU_ARRAY+=('Remove' ': Remove this interface configuration entirely') + fi + G_WHIP_MENU_ARRAY+=( + '' '●─ Apply ' + 'Apply' ': Save all changes and restart this interface' + ) + 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') G_WHIP_YESNO 'Would you like to enable this Ethernet adapter?' && CURRENT_IFACE_ENABLED=1 && Apply_Current_Interface 1;; + 'Disable') G_WHIP_YESNO 'Would you like to disable this Ethernet adapter?' && CURRENT_IFACE_ENABLED=0 && Apply_Current_Interface 1 && Return_From_Submenu "iface:$iface";; + 'Remove') G_WHIP_YESNO 'Would you like to remove this Ethernet adapter'\''s configuration entirely?\n\nUnlike "Disable", this removes the DietPi drop-in config file, so the interface can be freshly reconfigured later.' && { Remove_Interface_Config "$iface"; Return_From_Submenu "iface:$iface"; };; + 'Apply') G_WHIP_YESNO 'Apply settings and reconnect this Ethernet interface now?' && 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' ': Do not bring up interface at boot') + else + G_WHIP_MENU_ARRAY+=('Enable' ': Bring up interface at boot') + fi + G_WHIP_MENU_ARRAY+=('Remove' ': Remove this interface configuration entirely') + fi + G_WHIP_MENU_ARRAY+=( + '' '●─ Apply ' + 'Apply' ': Save all changes and restart this interface' + ) + 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 systemctl disable --now dietpi-wifi-monitor + else + G_EXEC systemctl enable --now dietpi-wifi-monitor + fi + ;; + 'Boot Mode') Change_BootMode;; + 'Enable') G_WHIP_YESNO 'Would you like to enable this WiFi adapter?' && CURRENT_IFACE_ENABLED=1 && Apply_Current_Interface 1;; + 'Disable') G_WHIP_YESNO 'Would you like to disable this WiFi adapter?' && CURRENT_IFACE_ENABLED=0 && G_EXEC systemctl disable --now dietpi-wifi-monitor && Apply_Current_Interface 1 && Return_From_Submenu "iface:$iface";; + 'Remove') G_WHIP_YESNO 'Would you like to remove this WiFi adapter'\''s configuration entirely?\n\nUnlike "Disable", this removes the DietPi drop-in config file, so the interface can be freshly reconfigured later.' && { G_EXEC_NOEXIT=1 G_EXEC systemctl disable --now dietpi-wifi-monitor; Remove_Interface_Config"$iface"; Return_From_Submenu "iface:$iface"; };; + 'Apply') + if (( $CURRENT_IFACE_HOTSPOT )) + then + Apply_Current_Interface 1 + else + G_WHIP_YESNO 'WiFi will connect to the strongest configured SSID that is secure. Save all changes and restart this WiFi interface now?' && Apply_Current_Interface 1 + fi + ;; + '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 systemctl stop hostapd + else + 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 c3560f70f0..4b4668482d 100755 --- a/dietpi/dietpi-software +++ b/dietpi/dietpi-software @@ -7845,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 @@ -7858,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; @@ -7879,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) @@ -7920,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 @@ -7936,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} @@ -7974,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 @@ -13975,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 @@ -13983,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 @@ -15276,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 f6339cb699..5be782e377 100755 --- a/dietpi/func/dietpi-banner +++ b/dietpi/func/dietpi-banner @@ -464,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 diff --git a/dietpi/func/dietpi-globals b/dietpi/func/dietpi-globals index 7391c4b0c4..d74a5d20bb 100644 --- a/dietpi/func/dietpi-globals +++ b/dietpi/func/dietpi-globals @@ -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-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..487266985f 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,24 @@ 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" --enable --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 + local ip=$INPUT_ADDITIONAL_1 + if [[ $ip && $INPUT_ADDITIONAL_3 ]] 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 + local cidr=$(mawk -v m="$INPUT_ADDITIONAL_3" '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}') + ip+="/$cidr" fi + /boot/dietpi/dietpi-network apply "$iface" --enable --static ${ip:+--ip "$ip"} ${INPUT_ADDITIONAL_2:+--gateway "$INPUT_ADDITIONAL_2"} ${INPUT_ADDITIONAL_4:+--dns "$INPUT_ADDITIONAL_4"} --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 1f3a9277bd..a0ca55d727 100644 --- a/rootfs/etc/bashrc.d/dietpi.bash +++ b/rootfs/etc/bashrc.d/dietpi.bash @@ -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' 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 } From 895c7a53b65029f920981b3ea5f8df0391751b94 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 23 Aug 2026 21:42:45 +0200 Subject: [PATCH 42/47] changelog: add entry about Orange Pi 5/5B --- CHANGELOG.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 9d041a0901..ece0d2b76c 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -11,6 +11,7 @@ Enhancements: 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-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 From 3c5e8ef67c0a2d357ceb9f3dfa687d972f752423 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 23 Aug 2026 21:59:40 +0200 Subject: [PATCH 43/47] changelog: add entry about Chromium --- CHANGELOG.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index ece0d2b76c..fd028df282 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -8,6 +8,7 @@ New tools: 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 From 9e171b2cf015ba3e6e5a1be7ad9ad98fed0f78a3 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 23 Aug 2026 22:05:07 +0200 Subject: [PATCH 44/47] changelog: add entry about banner fix --- CHANGELOG.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index fd028df282..0436f1a427 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -13,6 +13,7 @@ Enhancements: 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 From 40824596e49bc09a7f6a03c01f1de74b402952f7 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 23 Aug 2026 22:45:30 +0200 Subject: [PATCH 45/47] dietpi-set_software: allo: keep old behavior exactly The command did not touch the `allow-hotplug` line before, hence it should not actively enable interfaces now either. This keeps the current state, and only sets up new interfaces as enabled, which were not defined in any config file before. Elso enhance readability a bit. --- dietpi/func/dietpi-set_software | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/dietpi/func/dietpi-set_software b/dietpi/func/dietpi-set_software index 487266985f..54bf9f9ed2 100755 --- a/dietpi/func/dietpi-set_software +++ b/dietpi/func/dietpi-set_software @@ -521,17 +521,13 @@ deb $INPUT_MODE_VALUE $G_DISTRO_NAME-backports main contrib non-free non-free-fi local iface=$(G_GET_NET -t eth iface) if [[ $INPUT_MODE_VALUE == 'eth_dhcp' ]] then - /boot/dietpi/dietpi-network apply "$iface" --enable --dhcp --no-restart + /boot/dietpi/dietpi-network apply "$iface" --dhcp --no-restart elif [[ $INPUT_MODE_VALUE == 'eth_static' ]] then - local ip=$INPUT_ADDITIONAL_1 - if [[ $ip && $INPUT_ADDITIONAL_3 ]] - then - local cidr=$(mawk -v m="$INPUT_ADDITIONAL_3" '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}') - ip+="/$cidr" - fi - /boot/dietpi/dietpi-network apply "$iface" --enable --static ${ip:+--ip "$ip"} ${INPUT_ADDITIONAL_2:+--gateway "$INPUT_ADDITIONAL_2"} ${INPUT_ADDITIONAL_4:+--dns "$INPUT_ADDITIONAL_4"} --no-restart + 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 From a3b6e0403021228868b6634c136abdb90b2d99f3 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 23 Aug 2026 23:27:47 +0200 Subject: [PATCH 46/47] dietpi-network: add "Save" option So it is possible to save changes to the config, without applying them now. That way, e.g. the IP address can be changed without loosing the current SSH connections. Changes become effective from next reboot on. Remove the extra confirmation dialogs when applying changes or toggling states, and prevent hostapd and dietpi-wifi-monitor start/stop calls from exiting the script on failure. --- dietpi/dietpi-network | 47 ++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/dietpi/dietpi-network b/dietpi/dietpi-network index 45564fad9c..1ea71539c2 100755 --- a/dietpi/dietpi-network +++ b/dietpi/dietpi-network @@ -949,15 +949,16 @@ Menu_Interface() G_WHIP_MENU_ARRAY+=('' '●─ Toggle State ') if (( $CURRENT_IFACE_ENABLED )) then - G_WHIP_MENU_ARRAY+=('Disable' ': Do not bring up interface at boot') + G_WHIP_MENU_ARRAY+=('Disable' ': Stop and do not bring up interface at boot') else - G_WHIP_MENU_ARRAY+=('Enable' ': Bring up interface at boot') + 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 ' - 'Apply' ': Save all changes and restart this interface' + '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; } @@ -994,10 +995,11 @@ Menu_Interface() /boot/dietpi/func/dietpi-set_hardware eth-forcespeed "$G_WHIP_RETURNED_VALUE" "$iface" ;; 'Boot Mode') Change_BootMode;; - 'Enable') G_WHIP_YESNO 'Would you like to enable this Ethernet adapter?' && CURRENT_IFACE_ENABLED=1 && Apply_Current_Interface 1;; - 'Disable') G_WHIP_YESNO 'Would you like to disable this Ethernet adapter?' && CURRENT_IFACE_ENABLED=0 && Apply_Current_Interface 1 && Return_From_Submenu "iface:$iface";; - 'Remove') G_WHIP_YESNO 'Would you like to remove this Ethernet adapter'\''s configuration entirely?\n\nUnlike "Disable", this removes the DietPi drop-in config file, so the interface can be freshly reconfigured later.' && { Remove_Interface_Config "$iface"; Return_From_Submenu "iface:$iface"; };; - 'Apply') G_WHIP_YESNO 'Apply settings and reconnect this Ethernet interface now?' && Apply_Current_Interface 1;; + '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 @@ -1061,15 +1063,16 @@ Menu_Interface() G_WHIP_MENU_ARRAY+=('' '●─ Toggle State ') if (( $CURRENT_IFACE_ENABLED )) then - G_WHIP_MENU_ARRAY+=('Disable' ': Do not bring up interface at boot') + G_WHIP_MENU_ARRAY+=('Disable' ': Stop and do not bring up interface at boot') else - G_WHIP_MENU_ARRAY+=('Enable' ': Bring up interface at boot') + 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 ' - 'Apply' ': Save all changes and restart this interface' + '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; } @@ -1085,23 +1088,17 @@ Menu_Interface() 'Auto Reconnect') if (( $CURRENT_IFACE_WIFI_AUTO_RECONNECT )) then - G_EXEC systemctl disable --now dietpi-wifi-monitor + G_EXEC_NOEXIT=1 G_EXEC systemctl disable --now dietpi-wifi-monitor else - G_EXEC systemctl enable --now dietpi-wifi-monitor + G_EXEC_NOEXIT=1 G_EXEC systemctl enable --now dietpi-wifi-monitor fi ;; 'Boot Mode') Change_BootMode;; - 'Enable') G_WHIP_YESNO 'Would you like to enable this WiFi adapter?' && CURRENT_IFACE_ENABLED=1 && Apply_Current_Interface 1;; - 'Disable') G_WHIP_YESNO 'Would you like to disable this WiFi adapter?' && CURRENT_IFACE_ENABLED=0 && G_EXEC systemctl disable --now dietpi-wifi-monitor && Apply_Current_Interface 1 && Return_From_Submenu "iface:$iface";; - 'Remove') G_WHIP_YESNO 'Would you like to remove this WiFi adapter'\''s configuration entirely?\n\nUnlike "Disable", this removes the DietPi drop-in config file, so the interface can be freshly reconfigured later.' && { G_EXEC_NOEXIT=1 G_EXEC systemctl disable --now dietpi-wifi-monitor; Remove_Interface_Config"$iface"; Return_From_Submenu "iface:$iface"; };; - 'Apply') - if (( $CURRENT_IFACE_HOTSPOT )) - then - Apply_Current_Interface 1 - else - G_WHIP_YESNO 'WiFi will connect to the strongest configured SSID that is secure. Save all changes and restart this WiFi interface now?' && Apply_Current_Interface 1 - fi - ;; + '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}' @@ -1134,9 +1131,9 @@ Menu_Interface() 'State') if (( $CURRENT_IFACE_HOTSPOT_ACTIVE )) then - G_EXEC systemctl stop hostapd + G_EXEC_NOEXIT=1 G_EXEC systemctl stop hostapd else - G_EXEC systemctl start hostapd + 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"; };; From 06a6392128b3732113706fa437a2b41c554287e5 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 23 Aug 2026 23:30:33 +0200 Subject: [PATCH 47/47] RC up --- .update/version | 2 +- dietpi/func/dietpi-globals | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.update/version b/.update/version index 8d16d008b3..bebf0be975 100644 --- a/.update/version +++ b/.update/version @@ -3,7 +3,7 @@ # Available DietPi version G_REMOTE_VERSION_CORE=10 G_REMOTE_VERSION_SUB=7 -G_REMOTE_VERSION_RC=-1 +G_REMOTE_VERSION_RC=0 # Minimum DietPi version to allow update G_MIN_VERSION_CORE=8 G_MIN_VERSION_SUB=0 diff --git a/dietpi/func/dietpi-globals b/dietpi/func/dietpi-globals index d74a5d20bb..b083249585 100644 --- a/dietpi/func/dietpi-globals +++ b/dietpi/func/dietpi-globals @@ -55,7 +55,7 @@ # - Assign defaults/code version as fallback [[ $G_DIETPI_VERSION_CORE ]] || G_DIETPI_VERSION_CORE=10 [[ $G_DIETPI_VERSION_SUB ]] || G_DIETPI_VERSION_SUB=7 - [[ $G_DIETPI_VERSION_RC ]] || G_DIETPI_VERSION_RC=-1 + [[ $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
Total system count$SURVEY_COUNT_TOTAL
Systems sending survey data$SURVEY_COUNT_OPTIN$(( $SURVEY_COUNT_OPTIN * 100 / $SURVEY_COUNT_TOTAL ))%