diff --git a/CERTIFICATES.d/01-dialog-A.avif b/CERTIFICATES.d/01-dialog-A.avif
index ec5eb968..2fc3c9bd 100644
Binary files a/CERTIFICATES.d/01-dialog-A.avif and b/CERTIFICATES.d/01-dialog-A.avif differ
diff --git a/CERTIFICATES.d/02-dialog-B.avif b/CERTIFICATES.d/02-dialog-B.avif
index b2549c85..5e408abe 100644
Binary files a/CERTIFICATES.d/02-dialog-B.avif and b/CERTIFICATES.d/02-dialog-B.avif differ
diff --git a/CERTIFICATES.d/03-window.avif b/CERTIFICATES.d/03-window.avif
index a588614e..96039a3b 100644
Binary files a/CERTIFICATES.d/03-window.avif and b/CERTIFICATES.d/03-window.avif differ
diff --git a/CERTIFICATES.d/04-certificate.avif b/CERTIFICATES.d/04-certificate.avif
index de5ea9f9..e6663146 100644
Binary files a/CERTIFICATES.d/04-certificate.avif and b/CERTIFICATES.d/04-certificate.avif differ
diff --git a/CERTIFICATES.md b/CERTIFICATES.md
index 37e138ce..8ebd861e 100644
--- a/CERTIFICATES.md
+++ b/CERTIFICATES.md
@@ -32,13 +32,13 @@ is to use a desktop browser to get that information. This demonstration uses
[Mozilla Firefox ↗️](https://www.mozilla.org/firefox/).
Let's assume we want to make sure the certificate for
-[rsc.eworm.de](https://rsc.eworm.de/) is available. Open that page in the
-browser, then click the *shield* icon in addressbar, followed by
-"*Connection secure*".
+[git.eworm.de](https://git.eworm.de/) is available. Open that page in the
+browser, then click the *lock* icon in addressbar, followed by "*Connection
+secure*".

-The dialog will change, click "*More site information*".
+The dialog will change, click "*More information*".

diff --git a/INITIAL-COMMANDS.md b/INITIAL-COMMANDS.md
index df64aa7e..e033b576 100644
--- a/INITIAL-COMMANDS.md
+++ b/INITIAL-COMMANDS.md
@@ -18,9 +18,9 @@ Run the complete base installation:
{
:local BaseUrl "https://rsc.eworm.de/main/";
- :local CertCommonName "ISRG Root X2";
- :local CertFileName "ISRG-Root-X2.pem";
- :local CertFingerprint "69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470";
+ :local CertCommonName "Root YE";
+ :local CertFileName "Root-YE.pem";
+ :local CertFingerprint "e14ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666";
:local CertSettings [ /certificate/settings/get ];
:if (!((($CertSettings->"builtin-trust-anchors") = "trusted" || \
diff --git a/README.d/01-download-certs.avif b/README.d/01-download-certs.avif
index f2afeb54..e4d8755c 100644
Binary files a/README.d/01-download-certs.avif and b/README.d/01-download-certs.avif differ
diff --git a/README.d/03-check-certs.avif b/README.d/03-check-certs.avif
index 1f03ad2c..6610ac47 100644
Binary files a/README.d/03-check-certs.avif and b/README.d/03-check-certs.avif differ
diff --git a/README.d/12-setup-lease-script.avif b/README.d/12-setup-lease-script.avif
index 99f9c30c..2a8bcb24 100644
Binary files a/README.d/12-setup-lease-script.avif and b/README.d/12-setup-lease-script.avif differ
diff --git a/README.md b/README.md
index f7143ddf..b8f5b736 100644
--- a/README.md
+++ b/README.md
@@ -126,18 +126,18 @@ If you intend to download the scripts from a
different location (for example from github.com) install the corresponding
certificate chain.
- /tool/fetch "https://rsc.eworm.de/main/certs/ISRG-Root-X2.pem" dst-path="isrg-root-x2.pem";
+ /tool/fetch "https://rsc.eworm.de/main/certs/Root-YE.pem" dst-path="root-ye.pem";

> ℹ️ **Info**: Note that the command above does *not* verify server
> certificate, so if you want to be safe download with your workstations's
> browser from CA's website and transfer the file to your MikroTik device:
-> *Let's Encrypt* / *ISRG* [ISRG Root X2 ↗️](https://letsencrypt.org/certs/isrg-root-x2.pem)
+> *Let's Encrypt* / *ISRG* [Root YE ↗️](https://letsencrypt.org/certs/gen-y/root-ye.pem)
Then we import the certificate.
- /certificate/import file-name="isrg-root-x2.pem" passphrase="";
+ /certificate/import file-name="root-ye.pem" passphrase="";
Do not worry that the command is not shown - that happens because it contains
a sensitive property, the passphrase.
@@ -145,11 +145,11 @@ a sensitive property, the passphrase.

For basic verification we rename the certificate and print it by
-fingerprint. Make sure exactly this one certificate ("*ISRG-Root-X2*")
+fingerprint. Make sure exactly this one certificate ("*Root-YE*")
is shown.
- /certificate/set name="ISRG-Root-X2" [ find where common-name="ISRG Root X2" ];
- /certificate/print proplist=name,fingerprint where fingerprint="69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470";
+ /certificate/set name="Root-YE" [ find where common-name="Root YE" ];
+ /certificate/print proplist=name,fingerprint where fingerprint="e14ffcad5b0025731006caa43a121a22d8e9700f4fb9cf852f02a708aa5d5666";

@@ -258,8 +258,8 @@ Some events can run a script. If you want your DHCP hostnames to be available
in DNS use `dhcp-to-dns` with the events from dhcp server. For a regular
cleanup add a scheduler entry.
- $ScriptInstallUpdate dhcp-to-dns,dhcpv4-server-lease;
- /ip/dhcp-server/set lease-script="dhcpv4-server-lease" [ find ];
+ $ScriptInstallUpdate dhcp-to-dns,lease-script;
+ /ip/dhcp-server/set lease-script=lease-script [ find ];
/system/scheduler/add name="dhcp-to-dns" interval=5m start-time=startup on-event="/system/script/run dhcp-to-dns;";

@@ -286,8 +286,6 @@ Available scripts
* [Use wireless network with daily psk](doc/daily-psk.md) (`daily-psk`)
* [Comment DHCP leases with info from access list](doc/dhcp-lease-comment.md) (`dhcp-lease-comment`)
* [Create DNS records for DHCP leases](doc/dhcp-to-dns.md) (`dhcp-to-dns`)
-* [Run other scripts on IPv4 DHCP server lease](doc/dhcpv4-server-lease.md) (`dhcpv4-server-lease`)
-* [Run other scripts on IPv6 DHCP client lease](doc/dhcpv6-client-lease.md) (`dhcpv6-client-lease`)
* [Automatically upgrade firmware and reboot](doc/firmware-upgrade-reboot.md) (`firmware-upgrade-reboot`)
* [Download, import and update firewall address-lists](doc/fw-addr-lists.md) (`fw-addr-lists`)
* [Wait for global functions und modules](doc/global-wait.md) (`global-wait`)
@@ -296,6 +294,7 @@ Available scripts
* [Create DNS records for IPSec peers](doc/ipsec-to-dns.md) (`ipsec-to-dns`)
* [Update configuration on IPv6 prefix change](doc/ipv6-update.md) (`ipv6-update`)
* [Manage IP addresses with bridge status](doc/ip-addr-bridge.md) (`ip-addr-bridge`)
+* [Run other scripts on DHCP lease](doc/lease-script.md) (`lease-script`)
* [Manage LEDs dark mode](doc/leds-mode.md) (`leds-day-mode`, `leds-night-mode` & `leds-toggle-mode`)
* [Forward log messages via notification](doc/log-forward.md) (`log-forward`)
* [Mode button with multiple presses](doc/mode-button.md) (`mode-button`)
diff --git a/backup-email.rsc b/backup-email.rsc
index 70b18c06..fcafff45 100644
--- a/backup-email.rsc
+++ b/backup-email.rsc
@@ -16,7 +16,6 @@
do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50;
:local ScriptName [ :jobname ];
- :global BackupFileNameDate;
:global BackupPassword;
:global BackupRandomDelay;
:global BackupSendBinary;
@@ -74,9 +73,7 @@
# filename based on identity
:local DirName ("tmpfs/" . $ScriptName);
- :local Clock [ /system/clock/get ];
- :local FileName [ $CleanName ($Identity . "." . $Domain . [ $IfThenElse \
- ($BackupFileNameDate = true) ("-" . $Clock->"date" . "-" . $Clock->"time") "" ] ) ];
+ :local FileName [ $CleanName ($Identity . "." . $Domain) ];
:local FilePath ($DirName . "/" . $FileName);
:local BackupFile "none";
:local ExportFile "none";
diff --git a/backup-upload.rsc b/backup-upload.rsc
index b89d123d..bded570c 100644
--- a/backup-upload.rsc
+++ b/backup-upload.rsc
@@ -17,7 +17,6 @@
do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50;
:local ScriptName [ :jobname ];
- :global BackupFileNameDate;
:global BackupPassword;
:global BackupRandomDelay;
:global BackupSendBinary;
@@ -73,9 +72,7 @@
# filename based on identity
:local DirName ("tmpfs/" . $ScriptName);
- :local Clock [ /system/clock/get ];
- :local FileName [ $CleanName ($Identity . "." . $Domain . [ $IfThenElse \
- ($BackupFileNameDate = true) ("-" . $Clock->"date" . "-" . $Clock->"time") "" ] ) ];
+ :local FileName [ $CleanName ($Identity . "." . $Domain) ];
:local FilePath ($DirName . "/" . $FileName);
:local BackupFile "none";
:local ExportFile "none";
diff --git a/certs/Makefile b/certs/Makefile
index 8b516e4d..b0f029ab 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -12,12 +12,12 @@ DOMAINS_DUAL = \
cloudflare-dns.com/SSL-com-Root-Certification-Authority-ECC \
dns.google/GTS-Root-RX \
dns.quad9.net/DigiCert-Global-Root-G3 \
- git.eworm.de/ISRG-Root-X2 \
+ git.eworm.de/Root-YE \
gitlab.com/USERTrust-RSA-Certification-Authority \
lists.blocklist.de/GTS-Root-R4 \
matrix.org/GTS-Root-R4 \
- raw.githubusercontent.com/ISRG-Root-X1 \
- rsc.eworm.de/ISRG-Root-X2 \
+ raw.githubusercontent.com/USERTrust-RSA-Certification-Authority \
+ rsc.eworm.de/Root-YE \
upgrade.mikrotik.com/ISRG-Root-X1
DOMAINS_IPV4 = \
1.1.1.1/SSL-com-Root-Certification-Authority-ECC \
diff --git a/check-certificates.rsc b/check-certificates.rsc
index 7e2fed04..0122122a 100644
--- a/check-certificates.rsc
+++ b/check-certificates.rsc
@@ -60,8 +60,8 @@
http-header-field=({ [ $FetchUserAgentStr $ScriptName ] }) \
($CertRenewUrl . $CertFileName) dst-path=$CertFileName as-value;
} do={
- :if (!($Err ~ "[Ss]tatus 404")) do={
- $LogPrint warning $0 ("Failed fetching certificate by '" . $FetchName . "': " . $Err);
+ :if ($Err != "Fetch failed with status 404") do={
+ $LogPrint warning $0 ("Failed fetching certificate: " . $Err);
}
:error false;
}
@@ -164,8 +164,7 @@
}
$WaitFullyConnected;
- :foreach Cert in=[ /certificate/find where !revoked !scep-url expires-after<$CertRenewTime \
- !ca (common-name or subject-alt-name) ] do={
+ :foreach Cert in=[ /certificate/find where !revoked !ca !scep-url expires-after<$CertRenewTime ] do={
:local CertVal [ /certificate/get $Cert ];
:local LastName;
:local FetchName;
@@ -178,11 +177,9 @@
$LogPrint info $ScriptName ("Attempting to renew certificate '" . ($CertVal->"name") . "'.");
:local ImportSuccess false;
- :if ([ :len ($CertVal->"common-name") ] > 0) do={
- :set LastName ($CertVal->"common-name");
- :set FetchName $LastName;
- :set ImportSuccess [ $CheckCertificatesDownloadImport $ScriptName $LastName $FetchName ];
- }
+ :set LastName ($CertVal->"common-name");
+ :set FetchName $LastName;
+ :set ImportSuccess [ $CheckCertificatesDownloadImport $ScriptName $LastName $FetchName ];
:foreach SAN in=($CertVal->"subject-alt-name") do={
:if ($ImportSuccess = false) do={
:set LastName [ :pick $SAN ([ :find $SAN ":" ] + 1) [ :len $SAN ] ];
@@ -245,8 +242,8 @@
}
}
- :foreach Cert in=[ /certificate/find where !revoked !scep-url expires-after<$CertWarnTime \
- !(expires-after=[]) !(fingerprint=[]) ] do={
+ :foreach Cert in=[ /certificate/find where !revoked !scep-url !(expires-after=[]) \
+ expires-after<$CertWarnTime !(fingerprint=[]) ] do={
:local CertVal [ /certificate/get $Cert ];
:if ([ :len [ /certificate/scep-server/find where ca-cert=($CertVal->"ca") ] ] > 0) do={
diff --git a/collect-wireless-mac.capsman.rsc b/collect-wireless-mac.capsman.rsc
index 126153a0..8bb33d87 100644
--- a/collect-wireless-mac.capsman.rsc
+++ b/collect-wireless-mac.capsman.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2013-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# provides: dhcpv4-server-lease, order=40
+# provides: lease-script, order=40
# requires RouterOS, version=7.19
#
# collect wireless mac adresses in access list
diff --git a/collect-wireless-mac.local.rsc b/collect-wireless-mac.local.rsc
index f3ede554..9d41d420 100644
--- a/collect-wireless-mac.local.rsc
+++ b/collect-wireless-mac.local.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2013-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# provides: dhcpv4-server-lease, order=40
+# provides: lease-script, order=40
# requires RouterOS, version=7.19
#
# collect wireless mac adresses in access list
diff --git a/collect-wireless-mac.template.rsc b/collect-wireless-mac.template.rsc
index 1e1ed139..837726e3 100644
--- a/collect-wireless-mac.template.rsc
+++ b/collect-wireless-mac.template.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2013-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# provides: dhcpv4-server-lease, order=40
+# provides: lease-script, order=40
# requires RouterOS, version=7.19
#
# collect wireless mac adresses in access list
diff --git a/collect-wireless-mac.wifi.rsc b/collect-wireless-mac.wifi.rsc
index 35165a92..d07ff357 100644
--- a/collect-wireless-mac.wifi.rsc
+++ b/collect-wireless-mac.wifi.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2013-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# provides: dhcpv4-server-lease, order=40
+# provides: lease-script, order=40
# requires RouterOS, version=7.19
#
# collect wireless mac adresses in access list
diff --git a/contrib/html.sh b/contrib/html.sh
index adacbbb8..03eba23d 100755
--- a/contrib/html.sh
+++ b/contrib/html.sh
@@ -13,9 +13,7 @@ sed \
markdown -f toc,idanchor "${1}" | sed \
-e 's/href="\([-_\./[:alnum:]]*\)\.md\(#[-[:alnum:]]*\)\?"/href="\1.html\2"/g' \
-e '/| id="\L\1">|' \
- -e '//s|pre|pre class="code" onclick="CopyToClipboard(this)"|g' \
-e '/The above link may be broken on code hosting sites/s|blockquote|blockquote style="display: none;"|'
diff --git a/contrib/logo-color.d/browser-01.avif b/contrib/logo-color.d/browser-01.avif
index f758d1e7..3dc0a1f9 100644
Binary files a/contrib/logo-color.d/browser-01.avif and b/contrib/logo-color.d/browser-01.avif differ
diff --git a/contrib/logo-color.d/browser-02.avif b/contrib/logo-color.d/browser-02.avif
index 7679be16..1867fbe3 100644
Binary files a/contrib/logo-color.d/browser-02.avif and b/contrib/logo-color.d/browser-02.avif differ
diff --git a/contrib/logo-color.d/browser-03.avif b/contrib/logo-color.d/browser-03.avif
index 95732ad8..dc24bbbc 100644
Binary files a/contrib/logo-color.d/browser-03.avif and b/contrib/logo-color.d/browser-03.avif differ
diff --git a/contrib/logo-color.html b/contrib/logo-color.html
index c39a20b8..3e9c05fe 100644
--- a/contrib/logo-color.html
+++ b/contrib/logo-color.html
@@ -45,7 +45,7 @@ logo and download it.

(This example is with
-Mozilla Firefox ↗️. The workflow
+Firefox. The workflow
for other browsers may differ.)
See how to
diff --git a/contrib/telegram.md b/contrib/telegram.md
index 192fd6cb..36f7bc4e 100644
--- a/contrib/telegram.md
+++ b/contrib/telegram.md
@@ -91,14 +91,6 @@ Notes
/save dhcp-to-dns Create DNS records for DHCP leases with [dhcp-to-dns](https://rsc.eworm.de/doc/dhcp-to-dns.md).
-#### dhcpv4-server-lease
-
- /save dhcpv4-server-lease Run other scripts on IPv4 DHCP server lease with [dhcpv4-server-lease](https://rsc.eworm.de/doc/dhcpv4-server-lease.md).
-
-#### dhcpv6-client-lease
-
- /save dhcpv6-client-lease Run other scripts on IPv6 DHCP client lease with [dhcpv6-client-lease](https://rsc.eworm.de/doc/dhcpv6-client-lease.md).
-
#### firmware-upgrade-reboot
/save firmware-upgrade-reboot Automatically upgrade firmware and reboot with [firmware-upgrade-reboot](https://rsc.eworm.de/doc/firmware-upgrade-reboot.md).
@@ -131,6 +123,10 @@ Notes
/save ip-addr-bridge Manage IP addresses with [ip-addr-bridge](https://rsc.eworm.de/doc/ip-addr-bridge.md).
+#### lease-script
+
+ /save lease-script Run other scripts on DHCP lease with [lease-script](https://rsc.eworm.de/doc/lease-script.md).
+
#### leds-mode
/save leds-mode Manage LEDs dark mode with [leds-mode](https://rsc.eworm.de/doc/leds-mode.md).
diff --git a/dhcp-lease-comment.capsman.rsc b/dhcp-lease-comment.capsman.rsc
index d039cb02..7fd00a09 100644
--- a/dhcp-lease-comment.capsman.rsc
+++ b/dhcp-lease-comment.capsman.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2013-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# provides: dhcpv4-server-lease, order=60
+# provides: lease-script, order=60
# requires RouterOS, version=7.19
#
# update dhcp-server lease comment with infos from access-list
diff --git a/dhcp-lease-comment.local.rsc b/dhcp-lease-comment.local.rsc
index 2c5b4efa..7ed6823a 100644
--- a/dhcp-lease-comment.local.rsc
+++ b/dhcp-lease-comment.local.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2013-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# provides: dhcpv4-server-lease, order=60
+# provides: lease-script, order=60
# requires RouterOS, version=7.19
#
# update dhcp-server lease comment with infos from access-list
diff --git a/dhcp-lease-comment.template.rsc b/dhcp-lease-comment.template.rsc
index a06983f0..c901de40 100644
--- a/dhcp-lease-comment.template.rsc
+++ b/dhcp-lease-comment.template.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2013-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# provides: dhcpv4-server-lease, order=60
+# provides: lease-script, order=60
# requires RouterOS, version=7.19
#
# update dhcp-server lease comment with infos from access-list
diff --git a/dhcp-lease-comment.wifi.rsc b/dhcp-lease-comment.wifi.rsc
index 3fea1bf6..d481def8 100644
--- a/dhcp-lease-comment.wifi.rsc
+++ b/dhcp-lease-comment.wifi.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2013-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# provides: dhcpv4-server-lease, order=60
+# provides: lease-script, order=60
# requires RouterOS, version=7.19
#
# update dhcp-server lease comment with infos from access-list
diff --git a/dhcp-to-dns.rsc b/dhcp-to-dns.rsc
index 37aaadac..94c7492e 100644
--- a/dhcp-to-dns.rsc
+++ b/dhcp-to-dns.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2013-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# provides: dhcpv4-server-lease, order=20
+# provides: lease-script, order=20
# requires RouterOS, version=7.19
#
# check DHCP leases and add/remove/update DNS entries
@@ -51,6 +51,7 @@
active-address=($DnsRecordVal->"address") server=($DnsRecordInfo->"server") status=bound ] ] > 0) do={
$LogPrint debug $ScriptName ("Lease for " . $MacInServer . " (" . $DnsRecordVal->"name" . ") still exists. Not deleting record.");
} else={
+ :local Found false;
$LogPrint info $ScriptName ("Lease expired for " . $MacInServer . ", deleting record (" . $DnsRecordVal->"name" . ").");
/ip/dns/static/remove $DnsRecord;
/ip/dns/static/remove [ find where type=CNAME comment=($DnsRecordVal->"comment") ];
diff --git a/dhcpv4-server-lease.rsc b/dhcpv4-server-lease.rsc
deleted file mode 100644
index 899674d1..00000000
--- a/dhcpv4-server-lease.rsc
+++ /dev/null
@@ -1,65 +0,0 @@
-#!rsc by RouterOS
-# RouterOS script: dhcpv4-server-lease
-# Copyright (c) 2013-2026 Christian Hesse
-# https://rsc.eworm.de/COPYING.md
-#
-# requires RouterOS, version=7.19
-#
-# run scripts on IPv4 DHCP server lease
-# https://rsc.eworm.de/doc/dhcpv4-server-lease.md
-
-:local ExitOK false;
-:onerror Err {
- :global GlobalConfigReady; :global GlobalFunctionsReady;
- :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
- do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50;
- :local ScriptName [ :jobname ];
-
- :global Grep;
- :global IfThenElse;
- :global LogPrint;
- :global ParseKeyValueStore;
- :global ScriptLock;
-
- :if ([ :typeof $leaseActIP ] = "nothing" || \
- [ :typeof $leaseActMAC ] = "nothing" || \
- [ :typeof $leaseServerName ] = "nothing" || \
- [ :typeof $leaseBound ] = "nothing") do={
- $LogPrint error $ScriptName ("This script is supposed to run from ip dhcp-server.");
- :set ExitOK true;
- :error false;
- }
-
- $LogPrint debug $ScriptName ("DHCP Server " . $leaseServerName . " " . [ $IfThenElse ($leaseBound = 0) \
- "de" "" ] . "assigned lease " . $leaseActIP . " to " . $leaseActMAC);
-
- :if ([ $ScriptLock $ScriptName 10 ] = false) do={
- :set ExitOK true;
- :error false;
- }
-
- :if ([ :len [ /system/script/job/find where script=$ScriptName ] ] > 1) do={
- $LogPrint debug $ScriptName ("More invocations are waiting, exiting early.");
- :set ExitOK true;
- :error true;
- }
-
- :local RunOrder ({});
- :foreach Script in=[ /system/script/find where source~("\n# provides: dhcpv4-server-lease\\b") ] do={
- :local ScriptVal [ /system/script/get $Script ];
- :local Store [ $ParseKeyValueStore [ $Grep ($ScriptVal->"source") ("\23 provides: dhcpv4-server-lease, ") ] ];
-
- :set ($RunOrder->($Store->"order" . "-" . $ScriptVal->"name")) ($ScriptVal->"name");
- }
-
- :foreach Order,Script in=$RunOrder do={
- :onerror Err {
- $LogPrint debug $ScriptName ("Running script with order " . $Order . ": " . $Script);
- /system/script/run $Script;
- } do={
- $LogPrint warning $ScriptName ("Running script '" . $Script . "' failed: " . $Err);
- }
- }
-} do={
- :global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
-}
diff --git a/dhcpv6-client-lease.rsc b/dhcpv6-client-lease.rsc
deleted file mode 100644
index d3c1b9aa..00000000
--- a/dhcpv6-client-lease.rsc
+++ /dev/null
@@ -1,63 +0,0 @@
-#!rsc by RouterOS
-# RouterOS script: dhcpv6-client-lease
-# Copyright (c) 2026 Christian Hesse
-# https://rsc.eworm.de/COPYING.md
-#
-# requires RouterOS, version=7.19
-#
-# run scripts on IPv6 DHCP client lease
-# https://rsc.eworm.de/doc/dhcpv6-client-lease.md
-
-:local ExitOK false;
-:onerror Err {
- :global GlobalConfigReady; :global GlobalFunctionsReady;
- :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
- do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50;
- :local ScriptName [ :jobname ];
-
- :global Grep;
- :global LogPrint;
- :global ParseKeyValueStore;
- :global ScriptLock;
-
- :if ([ $ScriptLock $ScriptName 10 ] = false) do={
- :set ExitOK true;
- :error false;
- }
-
- :if (([ :typeof $"na-address" ] = "nothing" || [ :typeof $"na-valid" ] = "nothing") && \
- ([ :typeof $"pd-prefix" ] = "nothing" || [ :typeof $"pd-valid" ] = "nothing")) do={
- $LogPrint error $ScriptName ("This script is supposed to run from ipv6 dhcp-client.");
- :set ExitOK true;
- :error false;
- }
-
- :global DHCPv6ClientLeaseVars {
- "na-address"=$"na-address";
- "na-valid"=$"na-valid";
- "pd-prefix"=$"pd-prefix";
- "pd-valid"=$"pd-valid";
- "options"=$"options" };
-
- :local RunOrder ({});
- :foreach Script in=[ /system/script/find where source~("\n# provides: dhcpv6-client-lease\\b") ] do={
- :local ScriptVal [ /system/script/get $Script ];
- :local Store [ $ParseKeyValueStore [ $Grep ($ScriptVal->"source") ("\23 provides: dhcpv6-client-lease, ") ] ];
-
- :set ($RunOrder->($Store->"order" . "-" . $ScriptVal->"name")) ($ScriptVal->"name");
- }
-
- :foreach Order,Script in=$RunOrder do={
- :onerror Err {
- $LogPrint debug $ScriptName ("Running script with order " . $Order . ": " . $Script);
- /system/script/run $Script;
- } do={
- $LogPrint warning $ScriptName ("Running script '" . $Script . "' failed: " . $Err);
- }
- }
-
- :set DHCPv6ClientLeaseVars;
-} do={
- :global DHCPv6ClientLeaseVars; :set DHCPv6ClientLeaseVars;
- :global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
-}
diff --git a/doc/backup-email.md b/doc/backup-email.md
index e55a0d7b..cf334697 100644
--- a/doc/backup-email.md
+++ b/doc/backup-email.md
@@ -34,7 +34,6 @@ Configuration
The configuration goes to `global-config-overlay`, these are the parameters:
-* `BackupFileNameDate`: whether to add date & time in filenames
* `BackupSendBinary`: whether to send binary backup
* `BackupSendExport`: whether to send configuration export
* `BackupSendGlobalConfig`: whether to send `global-config-overlay`
diff --git a/doc/backup-upload.md b/doc/backup-upload.md
index bbf5227b..221cb721 100644
--- a/doc/backup-upload.md
+++ b/doc/backup-upload.md
@@ -40,7 +40,6 @@ Configuration
The configuration goes to `global-config-overlay`, these are the parameters:
-* `BackupFileNameDate`: whether to add date & time in filenames
* `BackupSendBinary`: whether to send binary backup
* `BackupSendExport`: whether to send configuration export
* `BackupSendGlobalConfig`: whether to send `global-config-overlay`
diff --git a/doc/check-certificates.md b/doc/check-certificates.md
index c6db7c88..1e69af46 100644
--- a/doc/check-certificates.md
+++ b/doc/check-certificates.md
@@ -85,7 +85,7 @@ Given you have a certificate on you server, you can use `check-certificates`
for the initial import. Just create a *dummy* certificate with short lifetime
that matches criteria to be renewed:
- /certificate/add name="example.com" common-name="example.com" subject-alt-name="DNS:example.com" days-valid=1;
+ /certificate/add name=example.com common-name=example.com days-valid=1;
/certificate/sign example.com;
/system/script/run check-certificates;
diff --git a/doc/collect-wireless-mac.md b/doc/collect-wireless-mac.md
index 96b314e1..9fef2adb 100644
--- a/doc/collect-wireless-mac.md
+++ b/doc/collect-wireless-mac.md
@@ -64,14 +64,14 @@ Usage and invocation
Run this script from a dhcp server as lease-script to collect the MAC
address when a new address is leased. You may want to use
-[dhcpv4-server-lease](dhcpv4-server-lease.md).
+[lease-script](lease-script.md).
See also
--------
* [Comment DHCP leases with info from access list](dhcp-lease-comment.md)
* [Create DNS records for DHCP leases](dhcp-to-dns.md)
-* [Run other scripts on IPv4 DHCP server lease](dhcpv4-server-lease.md)
+* [Run other scripts on DHCP lease](lease-script.md)
---
[⬅️ Go back to main README](../README.md)
diff --git a/doc/dhcp-lease-comment.md b/doc/dhcp-lease-comment.md
index 1a4e23aa..2bda80be 100644
--- a/doc/dhcp-lease-comment.md
+++ b/doc/dhcp-lease-comment.md
@@ -50,14 +50,14 @@ Usage and invocation
Run this script from a dhcp server as lease-script to update the comment
just after a new address is leased. You may want to use
-[dhcpv4-server-lease](dhcpv4-server-lease.md).
+[lease-script](lease-script.md).
See also
--------
* [Collect MAC addresses in wireless access list](collect-wireless-mac.md)
* [Create DNS records for DHCP leases](dhcp-to-dns.md)
-* [Run other scripts on IPv4 DHCP server lease](dhcpv4-server-lease.md)
+* [Run other scripts on DHCP lease](lease-script.md)
---
[⬅️ Go back to main README](../README.md)
diff --git a/doc/dhcp-to-dns.md b/doc/dhcp-to-dns.md
index 8c282b00..3636dfa3 100644
--- a/doc/dhcp-to-dns.md
+++ b/doc/dhcp-to-dns.md
@@ -28,7 +28,7 @@ Just install the script:
$ScriptInstallUpdate dhcp-to-dns;
Then run it from dhcp server as lease script. You may want to use
-[dhcpv4-server-lease](dhcpv4-server-lease.md).
+[lease-script](lease-script.md).
A scheduler cares about cleanup:
@@ -80,30 +80,13 @@ Note this information can be configured in wireless access list with
then due to script execution order. Decrease the scheduler interval to
reduce the effect.
-Frequently asked questions
---------------------------
-
-### Is it possible to have the hostname in reverse lookup?
-
-It used to be like that in the beginning. But there are way too many special
-cases... Devices without hostname, devices with same hostname, devices
-switching from one network to another, devices with same hostname in
-different network, ...
-
-Fixing one broke another. It never really worked without problems. So
-finally the code ended with what we have now.
-
-I know about that side effect and limitation with reverse lookup, but
-there's really no (easy) way to get that right without mac address. The
-reverse lookup will always give a name based on mac address.
-
See also
--------
* [Collect MAC addresses in wireless access list](collect-wireless-mac.md)
* [Comment DHCP leases with info from access list](dhcp-lease-comment.md)
-* [Run other scripts on IPv4 DHCP server lease](dhcpv4-server-lease.md)
* [Create DNS records for IPSec peers](ipsec-to-dns.md)
+* [Run other scripts on DHCP lease](lease-script.md)
---
[⬅️ Go back to main README](../README.md)
diff --git a/doc/dhcpv4-server-lease.md b/doc/dhcpv4-server-lease.md
deleted file mode 100644
index e588101d..00000000
--- a/doc/dhcpv4-server-lease.md
+++ /dev/null
@@ -1,54 +0,0 @@
-Run other scripts on IPv4 DHCP server lease
-===========================================
-
-[](https://github.com/eworm-de/routeros-scripts/stargazers)
-[](https://github.com/eworm-de/routeros-scripts/network)
-[](https://github.com/eworm-de/routeros-scripts/watchers)
-[](https://mikrotik.com/download/changelogs/)
-[](https://t.me/routeros_scripts)
-[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
-
-[⬅️ Go back to main README](../README.md)
-
-> ℹ️ **Info**: This script can not be used on its own but requires the base
-> installation. See [main README](../README.md) for details.
-
-Description
------------
-
-This script is supposed to run from IPv4 DHCP server as lease script. On a
-DHCP lease it runs each script containing the following line, where `##` is
-a decimal number for ordering:
-
- # provides: dhcpv4-server-lease, order=##
-
-Currently it runs if available, in order:
-
-* [dhcp-to-dns](dhcp-to-dns.md)
-* [collect-wireless-mac](collect-wireless-mac.md)
-* [dhcp-lease-comment](dhcp-lease-comment.md)
-* `hotspot-to-wpa-cleanup`, which is an optional cleanup script
- of [hotspot-to-wpa](hotspot-to-wpa.md)
-
-Requirements and installation
------------------------------
-
-Just install the script:
-
- $ScriptInstallUpdate dhcpv4-server-lease;
-
-... and add it as `lease-script` to your dhcp server:
-
- /ip/dhcp-server/set lease-script="dhcpv4-server-lease" [ find ];
-
-See also
---------
-
-* [Collect MAC addresses in wireless access list](collect-wireless-mac.md)
-* [Comment DHCP leases with info from access list](dhcp-lease-comment.md)
-* [Create DNS records for DHCP leases](dhcp-to-dns.md)
-* [Use WPA network with hotspot credentials](hotspot-to-wpa.md)
-
----
-[⬅️ Go back to main README](../README.md)
-[⬆️ Go back to top](#top)
diff --git a/doc/dhcpv6-client-lease.md b/doc/dhcpv6-client-lease.md
deleted file mode 100644
index c126f2d4..00000000
--- a/doc/dhcpv6-client-lease.md
+++ /dev/null
@@ -1,65 +0,0 @@
-Run other scripts on IPv6 DHCP client lease
-===========================================
-
-[](https://github.com/eworm-de/routeros-scripts/stargazers)
-[](https://github.com/eworm-de/routeros-scripts/network)
-[](https://github.com/eworm-de/routeros-scripts/watchers)
-[](https://mikrotik.com/download/changelogs/)
-[](https://t.me/routeros_scripts)
-[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
-
-[⬅️ Go back to main README](../README.md)
-
-> ℹ️ **Info**: This script can not be used on its own but requires the base
-> installation. See [main README](../README.md) for details.
-
-Description
------------
-
-This script is supposed to run from IPv6 DHCP client as lease script. On a
-DHCP leasse it runs each script containing the following line, where `##` is
-a decimal number for ordering:
-
- # provides: dhcpv6-client-lease, order=##
-
-The lease script is started with some variables injected, but these are not
-available in child scripts. However this script makes these variables
-available with a global variable. This code is required in child script:
-
- :global EitherOr;
-
- :global DHCPv6ClientLeaseVars;
-
- :local NaAddress [ $EitherOr $"na-address" ($DHCPv6ClientLeaseVars->"na-address") ];
- :local NaValid [ $EitherOr $"na-valid" ($DHCPv6ClientLeaseVars->"na-valid") ];
- :local PdPrefix [ $EitherOr $"pd-prefix" ($DHCPv6ClientLeaseVars->"pd-prefix") ];
- :local PdValid [ $EitherOr $"pd-valid" ($DHCPv6ClientLeaseVars->"pd-valid") ];
- :local Options [ $EitherOr $"options" ($DHCPv6ClientLeaseVars->"options") ];
-
-The values are available under different name then, use `$PdPrefix` instead
-of `$"pd-prefix"`, and so on. The resulting script supports both, being a
-lease script itself or being run as child.
-
-Currently it runs if available, in order:
-
-* [ipv6-update](ipv6-update.md)
-
-Requirements and installation
------------------------------
-
-Just install the script:
-
- $ScriptInstallUpdate dhcpv6-client-lease;
-
-... and add it as `lease-script` to your dhcp client:
-
- /ipv6/dhcp-client/set lease-script="dhcpv6-client-lease" [ find ];
-
-See also
---------
-
-* [Update configuration on IPv6 prefix change](ipv6-update.md)
-
----
-[⬅️ Go back to main README](../README.md)
-[⬆️ Go back to top](#top)
diff --git a/doc/hotspot-to-wpa.md b/doc/hotspot-to-wpa.md
index e4e77098..22d1dd13 100644
--- a/doc/hotspot-to-wpa.md
+++ b/doc/hotspot-to-wpa.md
@@ -49,24 +49,24 @@ and add a scheduler.
For `wifi`:
- $ScriptInstallUpdate hotspot-to-wpa-cleanup.wifi,dhcpv4-server-lease;
- /system/scheduler/add interval=1d name="hotspot-to-wpa-cleanup" on-event="/system/script/run hotspot-to-wpa-cleanup.wifi;" start-time=startup;
+ $ScriptInstallUpdate hotspot-to-wpa-cleanup.wifi,lease-script;
+ /system/scheduler/add interval=1d name=hotspot-to-wpa-cleanup on-event="/system/script/run hotspot-to-wpa-cleanup.wifi;" start-time=startup;
For legacy CAPsMAN:
- $ScriptInstallUpdate hotspot-to-wpa-cleanup.capsman,dhcpv4-server-lease;
- /system/scheduler/add interval=1d name="hotspot-to-wpa-cleanup" on-event="/system/script/run hotspot-to-wpa-cleanup.capsman;" start-time=startup;
+ $ScriptInstallUpdate hotspot-to-wpa-cleanup.capsman,lease-script;
+ /system/scheduler/add interval=1d name=hotspot-to-wpa-cleanup on-event="/system/script/run hotspot-to-wpa-cleanup.capsman;" start-time=startup;
And add the lease script and matcher comment to your wpa interfaces' dhcp
server. You can add more information to the comment, separated by comma. In
this example the server is called `hotspot-to-wpa`.
- /ip/dhcp-server/set lease-script="dhcpv4-server-lease" comment="hotspot-to-wpa=wpa" hotspot-to-wpa;
+ /ip/dhcp-server/set lease-script=lease-script comment="hotspot-to-wpa=wpa" hotspot-to-wpa;
You can specify the timeout after which a device is removed from leases and
access-list. The default is four weeks.
- /ip/dhcp-server/set lease-script="dhcpv4-server-lease" comment="hotspot-to-wpa=wpa, timeout=2w" hotspot-to-wpa;
+ /ip/dhcp-server/set lease-script=lease-script comment="hotspot-to-wpa=wpa, timeout=2w" hotspot-to-wpa;
Configuration
-------------
@@ -117,7 +117,7 @@ passphrase from hotspot credentials.
See also
--------
-* [Run other scripts on IPv4 DHCP server lease](dhcpv4-server-lease.md)
+* [Run other scripts on DHCP lease](lease-script.md)
---
[⬅️ Go back to main README](../README.md)
diff --git a/doc/ipv6-update.md b/doc/ipv6-update.md
index fb42e931..792f97e9 100644
--- a/doc/ipv6-update.md
+++ b/doc/ipv6-update.md
@@ -55,7 +55,7 @@ create it with:
/ipv6/firewall/address-list/add address=2003:cf:2f0f:de00::/56 comment=ipv6-pool-isp list=extern;
If the dynamic entry exists already you need to remove it before creating
-the static one.
+the static one..
Address list entries for specific interfaces can be updated as well. The
interface needs to get its address from pool `isp` and the address list entry
@@ -77,7 +77,6 @@ start with "`ipv6-pool-`" and actual pool name, followed by a comma,
See also
--------
-* [Run other scripts on IPv6 DHCP client lease](dhcpv6-client-lease.md)
* [Run scripts on ppp connection](ppp-on-up.md)
---
diff --git a/doc/lease-script.md b/doc/lease-script.md
index 3cba7045..6bcf7e13 100644
--- a/doc/lease-script.md
+++ b/doc/lease-script.md
@@ -1 +1,54 @@
-This script has been renamed. Please see [dhcpv4-server-lease](dhcpv4-server-lease.md).
+Run other scripts on DHCP lease
+===============================
+
+[](https://github.com/eworm-de/routeros-scripts/stargazers)
+[](https://github.com/eworm-de/routeros-scripts/network)
+[](https://github.com/eworm-de/routeros-scripts/watchers)
+[](https://mikrotik.com/download/changelogs/)
+[](https://t.me/routeros_scripts)
+[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
+
+[⬅️ Go back to main README](../README.md)
+
+> ℹ️ **Info**: This script can not be used on its own but requires the base
+> installation. See [main README](../README.md) for details.
+
+Description
+-----------
+
+This script is supposed to run from dhcp server as lease script. On a dhcp
+lease it runs each script containing the following line, where `##` is a
+decimal number for ordering:
+
+ # provides: lease-script, order=##
+
+Currently it runs if available, in order:
+
+* [dhcp-to-dns](dhcp-to-dns.md)
+* [collect-wireless-mac](collect-wireless-mac.md)
+* [dhcp-lease-comment](dhcp-lease-comment.md)
+* `hotspot-to-wpa-cleanup`, which is an optional cleanup script
+ of [hotspot-to-wpa](hotspot-to-wpa.md)
+
+Requirements and installation
+-----------------------------
+
+Just install the script:
+
+ $ScriptInstallUpdate lease-script;
+
+... and add it as `lease-script` to your dhcp server:
+
+ /ip/dhcp-server/set lease-script=lease-script [ find ];
+
+See also
+--------
+
+* [Collect MAC addresses in wireless access list](collect-wireless-mac.md)
+* [Comment DHCP leases with info from access list](dhcp-lease-comment.md)
+* [Create DNS records for DHCP leases](dhcp-to-dns.md)
+* [Use WPA network with hotspot credentials](hotspot-to-wpa.md)
+
+---
+[⬅️ Go back to main README](../README.md)
+[⬆️ Go back to top](#top)
diff --git a/doc/mod/notification-email.md b/doc/mod/notification-email.md
index cae7c94b..c45e917c 100644
--- a/doc/mod/notification-email.md
+++ b/doc/mod/notification-email.md
@@ -37,9 +37,7 @@ Also make sure the device has correct time configured, best is to set up
the ntp client.
Then edit `global-config-overlay`, add `EmailGeneralTo` with a valid
-recipient address. Optionally add `EmailServerCertificate` and add the CA
-certificate name if you have certificate verification enabled. Finally
-reload the configuration.
+recipient address. Finally reload the configuration.
> ℹ️ **Info**: Copy relevant configuration from
> [`global-config`](../../global-config.rsc) (the one without `-overlay`) to
diff --git a/doc/mod/ssh-keys-import.md b/doc/mod/ssh-keys-import.md
index c6530ec2..c2d3c951 100644
--- a/doc/mod/ssh-keys-import.md
+++ b/doc/mod/ssh-keys-import.md
@@ -4,7 +4,7 @@ Import ssh keys for public key authentication
[](https://github.com/eworm-de/routeros-scripts/stargazers)
[](https://github.com/eworm-de/routeros-scripts/network)
[](https://github.com/eworm-de/routeros-scripts/watchers)
-[](https://mikrotik.com/download/changelogs/)
+[](https://mikrotik.com/download/changelogs/)
[](https://t.me/routeros_scripts)
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
@@ -38,8 +38,9 @@ import that key:
$SSHKeysImport "ssh-rsa AAAAB3Nza...QYZk8= user" admin;
The third part of the key (`user` in this example) is inherited as
-`info` in RouterOS. Also the `MD5` fingerprint is recorded, this helps
-to audit and verify the available keys.
+`info` in RouterOS (or `key-owner` with RouterOS 7.20.x and before). Also
+the `MD5` fingerprint is recorded, this helps to audit and verify the
+available keys.
> ℹ️️ **Info**: Use `ssh-keygen` to show a fingerprint of an existing public
> key file: `ssh-keygen -l -E md5 -f ~/.ssh/id_ed25519.pub`
diff --git a/doc/ppp-on-up.md b/doc/ppp-on-up.md
index add5308f..e92601a2 100644
--- a/doc/ppp-on-up.md
+++ b/doc/ppp-on-up.md
@@ -36,7 +36,6 @@ Just install the script:
See also
--------
-* [Run other scripts on IPv6 DHCP client lease](dhcpv6-client-lease.md)
* [Update configuration on IPv6 prefix change](ipv6-update.md)
* [Update tunnelbroker configuration](update-tunnelbroker.md)
diff --git a/global-config.rsc b/global-config.rsc
index 0bb572b5..e8a86aac 100644
--- a/global-config.rsc
+++ b/global-config.rsc
@@ -31,8 +31,6 @@
:global EmailGeneralCc "";
#:global EmailGeneralTo "mail@example.com";
#:global EmailGeneralCc "another@example.com,third@example.com";
-# Add the CA certificate name here for verification.
-:global EmailServerCertificate "";
# You can send Telegram notifications. Register a bot
# and add the token and chat ids here, then install the module:
@@ -90,9 +88,7 @@
# Toggle this to disable color output in terminal/cli.
:global TerminalColorOutput true;
-# This defines whether to add date & time in filenames, what backups to generate,
-# the password to use, and what random delay (between 0 and given seconds) to apply.
-:global BackupFileNameDate false;
+# This defines what backups to generate and what password to use.
:global BackupSendBinary false;
:global BackupSendExport true;
:global BackupSendGlobalConfig true;
@@ -119,7 +115,7 @@
# cert="Root YE" };
{ url="https://raw.githubusercontent.com/stamparm/ipsum/refs/heads/master/levels/4.txt";
# # higher level (decrease the numerical value) for more addresses, and vice versa
- cert="ISRG Root X1" };
+ cert="USERTrust RSA Certification Authority" };
{ url="https://www.dshield.org/block.txt"; cidr="/24";
cert="GTS Root R4" };
{ url="https://lists.blocklist.de/lists/strongips.txt";
diff --git a/global-functions.rsc b/global-functions.rsc
index 30b0ccbc..e0a73045 100644
--- a/global-functions.rsc
+++ b/global-functions.rsc
@@ -15,7 +15,7 @@
# Git commit id & info, expected configuration version
:global CommitId "unknown";
:global CommitInfo "unknown";
-:global ExpectedConfigVersion 143;
+:global ExpectedConfigVersion 139;
# global variables not to be changed by user
:global GlobalFunctionsReady false;
@@ -111,13 +111,11 @@
:local UseFor [ :tostr $2 ];
:global CertificateDownload;
+ :global EitherOr;
:global LogPrint;
:global ParseKeyValueStore;
- :if ([ :len $UseFor ] = 0) do={
- $LogPrint warning $0 ("The intended use is undefined!");
- :set UseFor "undefined";
- }
+ :set UseFor [ $EitherOr $UseFor "undefined" ];
:if ([ /system/resource/get free-hdd-space ] < 8388608 && \
[ /certificate/settings/get crl-download ] = true && \
@@ -191,12 +189,7 @@
$LogPrint warning $0 ("Failed downloading certificate with CommonName '" . $CommonName . \
"' from repository! Trying fallback to mkcert.org...");
:do {
- :local CertSettings [ /certificate/settings/get ];
- :if ([ :len [ /certificate/find where common-name="ISRG Root X1" ] ] = 0 && \
- !((($CertSettings->"builtin-trust-anchors") = "trusted" || \
- ($CertSettings->"builtin-trust-store") ~ "fetch" || \
- ($CertSettings->"builtin-trust-store") = "all") && \
- [ :len [ /certificate/builtin/find where common-name="ISRG Root X1" ] ] > 0)) do={
+ :if ([ :len [ /certificate/find where common-name="ISRG Root X1" ] ] = 0) do={
$LogPrint error $0 ("Required certificate is not available.");
:return false;
}
@@ -310,7 +303,7 @@
:for I from=0 to=([ :len $Input ] - 1) do={
:local Char [ :pick $Input $I ];
- :if ([ :typeof [ :find "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" $Char ] ] = "nil") do={
+ :if ([ :typeof [ find "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" $Char ] ] = "nil") do={
:do {
:if ([ :len $Return ] = 0) do={
:error true;
@@ -812,15 +805,10 @@
# check if DNS is resolving
:set IsDNSResolving do={
:do {
- :local I 1;
- :retry {
- :set I ($I ^ 1);
- :resolve ("low-ttl.eworm." . ({ "de"; "net" }->$I));
- } delay=50ms max=6;
+ :resolve "low-ttl.eworm.de";
} on-error={
:return false;
}
-
:return true;
}
@@ -1205,12 +1193,10 @@
}
:onerror Err {
- /file/remove [ find where name=$DirName ];
+ /file/remove $DirName;
} do={
- :if (!($Err ~ "no such item")) do={
- $LogPrint error $0 ("Removing directory '" . $DirName . "' failed: " . $Err);
- :return false;
- }
+ $LogPrint error $0 ("Removing directory '" . $DirName . "' failed: " . $Err);
+ :return false;
}
:return true;
}
@@ -1236,12 +1222,10 @@
}
:onerror Err {
- /file/remove [ find where name=$FileName ];
+ /file/remove $FileName;
} do={
- :if (!($Err ~ "no such item")) do={
- $LogPrint error $0 ("Removing file '" . $FileName . "' failed: " . $Err);
- :return false;
- }
+ $LogPrint error $0 ("Removing file '" . $FileName . "' failed: " . $Err);
+ :return false;
}
:return true;
}
@@ -1301,15 +1285,12 @@
:global SymbolForNotification;
:global ValidateSyntax;
- :if ([ $CertificateAvailable "ISRG Root X2" "fetch" ] = false || \
- [ $CertificateAvailable "Root YE" "fetch" ] = false) do={
+ :if ([ $CertificateAvailable "Root YE" "fetch" ] = false) do={
$LogPrint warning $0 ("Downloading certificate failed, trying without.");
}
:foreach Script in=$Scripts do={
- :if ([ :len [ /system/script/find where name=$Script ] ] > 0) do={
- $LogPrint warning $0 ("Requested to add script '" . $Script . "', but that exists already!");
- } else={
+ :if ([ :len [ /system/script/find where name=$Script ] ] = 0) do={
$LogPrint info $0 ("Adding new script: " . $Script);
/system/script/add name=$Script owner=$Script source="#!rsc by RouterOS\n" comment=$NewComment;
}
diff --git a/hotspot-to-wpa-cleanup.capsman.rsc b/hotspot-to-wpa-cleanup.capsman.rsc
index 6f1ed372..35275313 100644
--- a/hotspot-to-wpa-cleanup.capsman.rsc
+++ b/hotspot-to-wpa-cleanup.capsman.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2021-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# provides: dhcpv4-server-lease, order=80
+# provides: lease-script, order=80
# requires RouterOS, version=7.19
# requires device-mode, hotspot
#
diff --git a/hotspot-to-wpa-cleanup.template.rsc b/hotspot-to-wpa-cleanup.template.rsc
index 8986b42d..398f194f 100644
--- a/hotspot-to-wpa-cleanup.template.rsc
+++ b/hotspot-to-wpa-cleanup.template.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2021-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# provides: dhcpv4-server-lease, order=80
+# provides: lease-script, order=80
# requires RouterOS, version=7.19
# requires device-mode, hotspot
#
diff --git a/hotspot-to-wpa-cleanup.wifi.rsc b/hotspot-to-wpa-cleanup.wifi.rsc
index 8a5a095c..17b9e545 100644
--- a/hotspot-to-wpa-cleanup.wifi.rsc
+++ b/hotspot-to-wpa-cleanup.wifi.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2021-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# provides: dhcpv4-server-lease, order=80
+# provides: lease-script, order=80
# requires RouterOS, version=7.19
# requires device-mode, hotspot
#
diff --git a/ipv6-update.rsc b/ipv6-update.rsc
index f93e2786..c87410cc 100644
--- a/ipv6-update.rsc
+++ b/ipv6-update.rsc
@@ -4,7 +4,6 @@
# https://rsc.eworm.de/COPYING.md
#
# requires RouterOS, version=7.19
-# provides: dhcpv6-client-lease, order=40
#
# update firewall and dns settings on IPv6 prefix change
# https://rsc.eworm.de/doc/ipv6-update.md
@@ -16,19 +15,16 @@
do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50;
:local ScriptName [ :jobname ];
- :global EitherOr;
:global LogPrint;
:global ParseKeyValueStore;
:global ScriptLock;
- :global DHCPv6ClientLeaseVars;
+ :local NaAddress $"na-address";
+ :local NaValid $"na-valid";
+ :local PdPrefix $"pd-prefix";
+ :local PdValid $"pd-valid";
- :local NaAddress [ $EitherOr $"na-address" ($DHCPv6ClientLeaseVars->"na-address") ];
- :local NaValid [ $EitherOr $"na-valid" ($DHCPv6ClientLeaseVars->"na-valid") ];
- :local PdPrefix [ $EitherOr $"pd-prefix" ($DHCPv6ClientLeaseVars->"pd-prefix") ];
- :local PdValid [ $EitherOr $"pd-valid" ($DHCPv6ClientLeaseVars->"pd-valid") ];
-
- :if ([ $ScriptLock $ScriptName 10 ] = false) do={
+ :if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
}
@@ -54,7 +50,7 @@
:local Pool [ /ipv6/pool/get [ find where prefix=$PdPrefix ] name ];
:if ([ :len [ /ipv6/firewall/address-list/find where comment=("ipv6-pool-" . $Pool) ] ] = 0) do={
/ipv6/firewall/address-list/add list=("ipv6-pool-" . $Pool) address=:: comment=("ipv6-pool-" . $Pool) dynamic=yes;
- $LogPrint info $ScriptName ("Added dynamic ipv6 address list entry for ipv6-pool-" . $Pool);
+ $LogPrint warning $ScriptName ("Added dynamic ipv6 address list entry for ipv6-pool-" . $Pool);
}
:local AddrList [ /ipv6/firewall/address-list/find where comment=("ipv6-pool-" . $Pool) ];
:local OldPrefix [ /ipv6/firewall/address-list/get ($AddrList->0) address ];
diff --git a/lease-script.rsc b/lease-script.rsc
index 2da00ca8..991e6fac 100644
--- a/lease-script.rsc
+++ b/lease-script.rsc
@@ -1,3 +1,65 @@
#!rsc by RouterOS
+# RouterOS script: lease-script
+# Copyright (c) 2013-2026 Christian Hesse
+# https://rsc.eworm.de/COPYING.md
#
-# dummy for migration
+# requires RouterOS, version=7.19
+#
+# run scripts on DHCP lease
+# https://rsc.eworm.de/doc/lease-script.md
+
+:local ExitOK false;
+:onerror Err {
+ :global GlobalConfigReady; :global GlobalFunctionsReady;
+ :retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
+ do={ :error ("Global config and/or functions not ready."); }; } delay=500ms max=50;
+ :local ScriptName [ :jobname ];
+
+ :global Grep;
+ :global IfThenElse;
+ :global LogPrint;
+ :global ParseKeyValueStore;
+ :global ScriptLock;
+
+ :if ([ :typeof $leaseActIP ] = "nothing" || \
+ [ :typeof $leaseActMAC ] = "nothing" || \
+ [ :typeof $leaseServerName ] = "nothing" || \
+ [ :typeof $leaseBound ] = "nothing") do={
+ $LogPrint error $ScriptName ("This script is supposed to run from ip dhcp-server.");
+ :set ExitOK true;
+ :error false;
+ }
+
+ $LogPrint debug $ScriptName ("DHCP Server " . $leaseServerName . " " . [ $IfThenElse ($leaseBound = 0) \
+ "de" "" ] . "assigned lease " . $leaseActIP . " to " . $leaseActMAC);
+
+ :if ([ $ScriptLock $ScriptName 10 ] = false) do={
+ :set ExitOK true;
+ :error false;
+ }
+
+ :if ([ :len [ /system/script/job/find where script=$ScriptName ] ] > 1) do={
+ $LogPrint debug $ScriptName ("More invocations are waiting, exiting early.");
+ :set ExitOK true;
+ :error true;
+ }
+
+ :local RunOrder ({});
+ :foreach Script in=[ /system/script/find where source~("\n# provides: lease-script\\b") ] do={
+ :local ScriptVal [ /system/script/get $Script ];
+ :local Store [ $ParseKeyValueStore [ $Grep ($ScriptVal->"source") ("\23 provides: lease-script, ") ] ];
+
+ :set ($RunOrder->($Store->"order" . "-" . $ScriptVal->"name")) ($ScriptVal->"name");
+ }
+
+ :foreach Order,Script in=$RunOrder do={
+ :onerror Err {
+ $LogPrint debug $ScriptName ("Running script with order " . $Order . ": " . $Script);
+ /system/script/run $Script;
+ } do={
+ $LogPrint warning $ScriptName ("Running script '" . $Script . "' failed: " . $Err);
+ }
+ }
+} do={
+ :global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
+}
diff --git a/mod/notification-email.rsc b/mod/notification-email.rsc
index b6288821..b14e1868 100644
--- a/mod/notification-email.rsc
+++ b/mod/notification-email.rsc
@@ -37,9 +37,7 @@
# flush e-mail queue
:set FlushEmailQueue do={ :onerror Err {
:global EmailQueue;
- :global EmailServerCertificate;
- :global CertificateAvailable;
:global EitherOr;
:global EMailGenerateFrom;
:global FileExists;
@@ -50,10 +48,11 @@
:local AllDone true;
:local QueueLen [ :len $EmailQueue ];
+ :local Scheduler [ /system/scheduler/find where name="_FlushEmailQueue" ];
- :if ([ :len [ /system/scheduler/find where name="_FlushEmailQueue" ] ] > 0 && $QueueLen = 0) do={
+ :if ([ :len $Scheduler ] > 0 && $QueueLen = 0) do={
$LogPrint warning $0 ("Flushing E-Mail messages from scheduler, but queue is empty.");
- /system/scheduler/remove [ find where name="_FlushEmailQueue" ];
+ /system/scheduler/remove $Scheduler;
:return false;
}
@@ -61,19 +60,15 @@
:return true;
}
- :if ([ :len [ /system/scheduler/find where name="_FlushEmailQueue" ] ] < 0) do={
+ :if ([ :len $Scheduler ] < 0) do={
/system/scheduler/add name="_FlushEmailQueue" interval=1m start-time=startup \
comment="Doing initial checks..." on-event=(":global FlushEmailQueue; \$FlushEmailQueue;");
+ :set Scheduler [ /system/scheduler/find where name="_FlushEmailQueue" ];
}
- :do {
- :if (([ /system/scheduler/get [ find where name="_FlushEmailQueue" ] ]->"interval") < 1m) do={
- /system/scheduler/set interval=1m comment="Doing initial checks..." \
- [ find where name="_FlushEmailQueue" ];
- }
- } on-error={
- $LogPrint debug $0 ("The scheduler is gone, aborting.");
- :return false;
+ :local SchedVal [ /system/scheduler/get $Scheduler ];
+ :if (($SchedVal->"interval") < 1m) do={
+ /system/scheduler/set interval=1m comment="Doing initial checks..." $Scheduler;
}
:if ([ /tool/e-mail/get last-status ] = "in-progress") do={
@@ -92,16 +87,7 @@
:return false;
}
- :if (([ /tool/e-mail/get ]->"certificate-verification") ~ "^yes" && \
- [ :len $EmailServerCertificate ] > 0) do={
- :if ([ $CertificateAvailable $EmailServerCertificate "email" ] = false) do={
- $LogPrint warning $0 ("Downloading required certificate failed.");
- :return false;
- }
- }
-
- /system/scheduler/set interval=($QueueLen . "m") comment="Sending..." \
- [ find where name="_FlushEmailQueue" ];
+ /system/scheduler/set interval=($QueueLen . "m") comment="Sending..." $Scheduler;
:foreach Id,Message in=$EmailQueue do={
:if ([ :typeof $Message ] = "array" ) do={
@@ -157,8 +143,8 @@
:return false;
}
- /system/scheduler/set interval=(([ get [ find where name="_FlushEmailQueue" ] ]->"run-count") . "m") \
- comment="Waiting for retry..." [ find where name="_FlushEmailQueue" ];
+ /system/scheduler/set interval=(($SchedVal->"run-count") . "m") \
+ comment="Waiting for retry..." $Scheduler;
} do={
:global ExitOnError; $ExitOnError $0 $Err;
} }
diff --git a/mod/ssh-keys-import.rsc b/mod/ssh-keys-import.rsc
index ea8bf130..d1cc4fa3 100644
--- a/mod/ssh-keys-import.rsc
+++ b/mod/ssh-keys-import.rsc
@@ -3,7 +3,7 @@
# Copyright (c) 2020-2026 Christian Hesse
# https://rsc.eworm.de/COPYING.md
#
-# requires RouterOS, version=7.21
+# requires RouterOS, version=7.19
#
# import ssh keys for public key authentication
# https://rsc.eworm.de/doc/mod/ssh-keys-import.md
@@ -40,8 +40,9 @@
:local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex ($KeyVal->1) ];
+ :local RegEx ("\\bmd5=" . $FingerPrintMD5 . "\\b");
:if ([ :len [ /user/ssh-keys/find where user=$User \
- info~("\\bmd5=" . $FingerPrintMD5 . "\\b") ] ] > 0) do={
+ (key-owner~$RegEx or info~$RegEx) ] ] > 0) do={
$LogPrint warning $0 ("The ssh public key (MD5:" . $FingerPrintMD5 . \
") is already available for user '" . $User . "'.");
:return false;
diff --git a/netwatch-dns.rsc b/netwatch-dns.rsc
index 7c6a7b5b..9531d4ad 100644
--- a/netwatch-dns.rsc
+++ b/netwatch-dns.rsc
@@ -115,15 +115,13 @@
:local Data false;
:onerror Err {
- :local I 1;
:retry {
- :set I ($I ^ 1);
:set Data ([ /tool/fetch check-certificate=yes-without-crl output=user \
http-header-field=({ "accept: application/dns-message" }) \
url=(($DohServer->"doh-url") . "?dns=" . [ :convert to=base64 ([ :rndstr length=2 ] . \
- "\01\00" . "\00\01" . "\00\00" . "\00\00" . "\00\00" . "\09doh-check\05eworm" . \
- ({ "\02de"; "\03net" }->$I) . "\00" . "\00\10" . "\00\01") ]) as-value ]->"data");
- } delay=500ms max=6;
+ "\01\00" . "\00\01" . "\00\00" . "\00\00" . "\00\00" . "\09doh-check\05eworm\02de\00" . \
+ "\00\10" . "\00\01") ]) as-value ]->"data");
+ } delay=1s max=3;
} do={
$LogPrint warning $ScriptName ("Request to DoH server " . ($DohServer->"doh-url") . \
" failed: " . $Err);
diff --git a/news-and-changes.rsc b/news-and-changes.rsc
index ed60a6c2..709e7744 100644
--- a/news-and-changes.rsc
+++ b/news-and-changes.rsc
@@ -64,19 +64,14 @@
137="Added support to send notifications via Gotify (gotify.net).";
138="RouterOS 7.19 is suffering an issue with certificate store. Fixing trust state for all certificates...";
139="Certificate Authorities will reduce the leaf certificate validity times soon. Thus the defaults for renewal and warning in 'check-certificates' were decreased.";
- 140="The scripts 'lease-script' was renamed to 'dhcpv4-server-lease', configuration was updated automatically.";
- 141="Introduced script 'dhcpv6-client-lease' to run several scripts on IPv6 DHCP client lease.";
- 142="Added a setting for 'mod/notification-email' to check availability of certificate chain.";
- 143="Made backup scripts 'backup-email' and 'backup-upload' support date & time in filenames.";
};
# Migration steps to be applied on script updates
:global GlobalConfigMigration {
- 97=":local Rec [ /ip/dns/static/find where comment~\"^managed by dhcp-to-dns for \" ]; :if ([ :len \$Rec ] > 0) do={ /ip/dns/static/remove \$Rec; /system/script/run dhcp-to-dns; };";
- 100=":global ScriptInstallUpdate; :if ([ :len [ /system/script/find where name=\"ssh-keys-import\" source~\"^#!rsc by RouterOS\\r?\\n\" ] ] > 0) do={ /system/script/set name=\"mod/ssh-keys-import\" ssh-keys-import; \$ScriptInstallUpdate; };";
+ 97=":local Rec [ /ip/dns/static/find where comment~\"^managed by dhcp-to-dns for \" ]; :if ([ :len \$Rec ] > 0) do={ /ip/dns/static/remove \$Rec; /system/script/run dhcp-to-dns; }";
+ 100=":global ScriptInstallUpdate; :if ([ :len [ /system/script/find where name=\"ssh-keys-import\" source~\"^#!rsc by RouterOS\\r?\\n\" ] ] > 0) do={ /system/script/set name=\"mod/ssh-keys-import\" ssh-keys-import; \$ScriptInstallUpdate; }";
104=":global CharacterReplace; :global ScriptInstallUpdate; :foreach Script in={ \"capsman-download-packages\"; \"capsman-rolling-upgrade\"; \"hotspot-to-wpa\"; \"hotspot-to-wpa-cleanup\" } do={ /system/script/set name=(\$Script . \".capsman\") [ find where name=\$Script ]; :foreach Scheduler in=[ /system/scheduler/find where on-event~(\$Script . \"([^-.]|\\\$)\") ] do={ /system/scheduler/set \$Scheduler on-event=[ \$CharacterReplace [ get \$Scheduler on-event ] \$Script (\$Script . \".capsman\") ]; }; }; /ip/hotspot/user/profile/set on-login=\"hotspot-to-wpa.capsman\" [ find where on-login=\"hotspot-to-wpa\" ]; \$ScriptInstallUpdate;";
- 111=":local Rec [ /ip/dns/static/find where comment~\"^managed by dhcp-to-dns for \" ]; :if ([ :len \$Rec ] > 0) do={ /ip/dns/static/remove \$Rec; /system/script/run dhcp-to-dns; };";
- 132=":if ([ :len [ /system/script/find where name=\"check-health\" ] ] > 0) do={ :local Code \":local Install \\\"check-health\\\"; :if ([ :len [ /system/health/find where type=\\\"\\\" name~\\\"-state\\\\\\\$\\\" ] ] > 0) do={ :set Install (\\\$Install . \\\",check-health.d/state\\\"); }; :if ([ :len [ /system/health/find where type=\\\"C\\\" ] ] > 0) do={ :set Install (\\\$Install . \\\",check-health.d/temperature\\\"); }; :if ([ :len [ /system/health/find where type=\\\"V\\\" ] ] > 0) do={ :set Install (\\\$Install . \\\",check-health.d/voltage\\\"); }; :global ScriptInstallUpdate; \\\$ScriptInstallUpdate \\\$Install;\"; :global ValidateSyntax; :if ([ \$ValidateSyntax \$Code ] = true) do={ :do { [ :parse \$Code ]; } on-error={ }; }; };";
+ 111=":local Rec [ /ip/dns/static/find where comment~\"^managed by dhcp-to-dns for \" ]; :if ([ :len \$Rec ] > 0) do={ /ip/dns/static/remove \$Rec; /system/script/run dhcp-to-dns; }";
+ 132=":if ([ :len [ /system/script/find where name=\"check-health\" ] ] > 0) do={ :local Code \":local Install \\\"check-health\\\"; :if ([ :len [ /system/health/find where type=\\\"\\\" name~\\\"-state\\\\\\\$\\\" ] ] > 0) do={ :set Install (\\\$Install . \\\",check-health.d/state\\\"); }; :if ([ :len [ /system/health/find where type=\\\"C\\\" ] ] > 0) do={ :set Install (\\\$Install . \\\",check-health.d/temperature\\\"); }; :if ([ :len [ /system/health/find where type=\\\"V\\\" ] ] > 0) do={ :set Install (\\\$Install . \\\",check-health.d/voltage\\\"); }; :global ScriptInstallUpdate; \\\$ScriptInstallUpdate \\\$Install;\"; :global ValidateSyntax; :if ([ \$ValidateSyntax \$Code ] = true) do={ :do { [ :parse \$Code ]; } on-error={ }; }; }";
138="/certificate/set trusted=yes [ find where trusted=yes ];";
- 140=":if ([ :len [ /system/script/find where name=\"lease-script\" ] ] > 0) do={ /system/script/set name=\"dhcpv4-server-lease\" \"lease-script\"; :global ScriptInstallUpdate; \$ScriptInstallUpdate; /ip/dhcp-server/set lease-script=\"dhcpv4-server-lease\" [ find where lease-script=\"lease-script\" ]; };";
};