Compare commits

...

8 commits

Author SHA1 Message Date
Christian Hesse
31a4e95383 global-functions: $NetMask6: use shift operator...
... and drop the workaround. This requires RouterOS 7.22beta3.
2026-01-22 07:07:06 +01:00
Christian Hesse
f4ac5792d2 Merge branch 'continue-in-loop' into next 2026-01-22 07:07:06 +01:00
Christian Hesse
a1694a972e check-certificates: use :continue in loop 2026-01-22 07:07:06 +01:00
Christian Hesse
c1ce74bddf global-functions: $ScriptInstallUpdate: fix indention 2026-01-22 07:07:06 +01:00
Christian Hesse
ee7b59c8fb global-functions: $ScriptInstallUpdate: use :continue in loop 2026-01-22 07:07:06 +01:00
Christian Hesse
8503752957 fw-addr-lists: fix indention 2026-01-22 07:07:06 +01:00
Christian Hesse
259933dbf9 fw-addr-lists: use :continue in loop 2026-01-22 07:07:06 +01:00
Christian Hesse
69a4aab891 telegram-chat: use :continue in loop 2026-01-22 07:07:06 +01:00
4 changed files with 124 additions and 150 deletions

View file

@ -161,7 +161,7 @@
:do {
:if ([ :len $CertRenewUrl ] = 0) do={
$LogPrintOnce info $ScriptName ("No CertRenewUrl given.");
:error false;
:continue;
}
$LogPrint info $ScriptName ("Attempting to renew certificate '" . ($CertVal->"name") . "'.");

View file

@ -111,41 +111,40 @@
} else={
:set Address ([ :pick $Line 0 [ $FindDelim $Line ] ] . ($List->"cidr"));
}
:do {
:local Branch;
:if ($Address ~ "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}(/[0-9]{1,2})?\$") do={
:local Net $Address;
:local CIDR 32;
:local Slash [ :find $Address "/" ];
:if ([ :typeof $Slash ] = "num") do={
:set Net [ :toip [ :pick $Address 0 $Slash ] ]
:set CIDR [ :pick $Address ($Slash + 1) [ :len $Address ] ];
:set Address [ :tostr (([ :toip $Net ] & [ $NetMask4 $CIDR ]) . [ $IfThenElse ($CIDR < 32) ("/" . $CIDR) ]) ];
}
:set Branch [ $GetBranch $Address ];
:set ($IPv4Addresses->$Branch->$Address) $TimeOut;
:error true;
:local Branch;
:if ($Address ~ "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}(/[0-9]{1,2})?\$") do={
:local Net $Address;
:local CIDR 32;
:local Slash [ :find $Address "/" ];
:if ([ :typeof $Slash ] = "num") do={
:set Net [ :toip [ :pick $Address 0 $Slash ] ]
:set CIDR [ :pick $Address ($Slash + 1) [ :len $Address ] ];
:set Address [ :tostr (([ :toip $Net ] & [ $NetMask4 $CIDR ]) . [ $IfThenElse ($CIDR < 32) ("/" . $CIDR) ]) ];
}
:if ($Address ~ "^[0-9a-zA-Z]*:[0-9a-zA-Z:\\.]+(/[0-9]{1,3})?\$") do={
:local Net $Address;
:local CIDR 128;
:local Slash [ :find $Address "/" ];
:if ([ :typeof $Slash ] = "num") do={
:set Net [ :toip6 [ :pick $Address 0 $Slash ] ]
:set CIDR [ :pick $Address ($Slash + 1) [ :len $Address ] ];
}
:set Address (([ :toip6 $Net ] & [ $NetMask6 $CIDR ]) . "/" . $CIDR);
:set Branch [ $GetBranch $Address ];
:set ($IPv6Addresses->$Branch->$Address) $TimeOut;
:error true;
:set Branch [ $GetBranch $Address ];
:set ($IPv4Addresses->$Branch->$Address) $TimeOut;
:continue;
}
:if ($Address ~ "^[0-9a-zA-Z]*:[0-9a-zA-Z:\\.]+(/[0-9]{1,3})?\$") do={
:local Net $Address;
:local CIDR 128;
:local Slash [ :find $Address "/" ];
:if ([ :typeof $Slash ] = "num") do={
:set Net [ :toip6 [ :pick $Address 0 $Slash ] ]
:set CIDR [ :pick $Address ($Slash + 1) [ :len $Address ] ];
}
:if ($Address ~ "^[\\.a-zA-Z0-9-]+\\.[a-zA-Z]{2,}\$") do={
:set Branch [ $GetBranch $Address ];
:set ($IPv4Addresses->$Branch->$Address) $TimeOut;
:set ($IPv6Addresses->$Branch->$Address) $TimeOut;
:error true;
}
} on-error={ }
:set Address (([ :toip6 $Net ] & [ $NetMask6 $CIDR ]) . "/" . $CIDR);
:set Branch [ $GetBranch $Address ];
:set ($IPv6Addresses->$Branch->$Address) $TimeOut;
:continue;
}
:if ($Address ~ "^[\\.a-zA-Z0-9-]+\\.[a-zA-Z]{2,}\$") do={
:set Branch [ $GetBranch $Address ];
:set ($IPv4Addresses->$Branch->$Address) $TimeOut;
:set ($IPv6Addresses->$Branch->$Address) $TimeOut;
:continue;
}
}
}

View file

@ -1014,31 +1014,9 @@
# return an IPv6 netmask for CIDR
:set NetMask6 do={
:local CIDR [ :tostr $1 ];
:local CIDR [ :tonum $1 ];
:global IfThenElse;
:global MAX;
:global MIN;
:global NetMask6Cache;
:if ([ :typeof ($NetMask6Cache->$CIDR) ] = "ip6") do={
:return ($NetMask6Cache->$CIDR);
}
:if ([ :typeof $NetMask6Cache ] = "nothing") do={
:set NetMask6Cache ({});
}
:local Mask "";
:for I from=0 to=7 do={
:set Mask ($Mask . \
[ :convert from=num to=hex (0xffff - (0xffff >> [ :tonum [ $MIN [ $MAX ($CIDR - (16 * $I)) 0 ] 16 ] ])) ] . \
[ $IfThenElse ($I < 7) ":" ]);
}
:set Mask [ :toip6 $Mask ];
:set ($NetMask6Cache->$CIDR) $Mask;
:return $Mask;
:return (((~::) << (128 - $CIDR)) & (~::));
}
# prepare NotificationFunctions array
@ -1290,105 +1268,103 @@
}
}
:do {
:if ($ScriptInfo->"ignore" = true) do={
$LogPrint debug $0 ("Ignoring script '" . $ScriptVal->"name" . "', as requested.");
:error true;
:if ($ScriptInfo->"ignore" = true) do={
$LogPrint debug $0 ("Ignoring script '" . $ScriptVal->"name" . "', as requested.");
:continue;
}
:local CheckSum ($CheckSums->($ScriptVal->"name"));
:if ([ :len ($ScriptInfo->"base-url") ] = 0 && [ :len ($ScriptInfo->"url-suffix") ] = 0 && \
[ :convert transform=md5 to=hex [ :tolf ($ScriptVal->"source") ] ] = $CheckSum) do={
$LogPrint debug $0 ("Checksum for script '" . $ScriptVal->"name" . "' matches, ignoring.");
:continue;
}
:if ([ :len ($ScriptInfo->"certificate") ] > 0) do={
:if ([ $CertificateAvailable ($ScriptInfo->"certificate") "fetch" ] = false) do={
$LogPrint warning $0 ("Downloading certificate failed, trying without.");
}
}
:onerror Err {
:local BaseUrl [ $EitherOr ($ScriptInfo->"base-url") $ScriptUpdatesBaseUrl ];
:local UrlSuffix [ $EitherOr ($ScriptInfo->"url-suffix") $ScriptUpdatesUrlSuffix ];
:local Url ($BaseUrl . $ScriptVal->"name" . ".rsc" . $UrlSuffix);
$LogPrint debug $0 ("Fetching script '" . $ScriptVal->"name" . "' from url: " . $Url);
:local Result [ /tool/fetch check-certificate=yes-without-crl \
http-header-field=({ [ $FetchUserAgentStr $0 ] }) $Url output=user as-value ];
:if ($Result->"status" = "finished") do={
:set SourceNew [ :tolf ($Result->"data") ];
}
} do={
$LogPrint warning $0 ("Failed fetching script '" . $ScriptVal->"name" . "': " . $Err);
:if ($Err != "Fetch failed with status 404") do={
:continue;
}
:local CheckSum ($CheckSums->($ScriptVal->"name"));
:if ($ScriptVal->"source" = "#!rsc by RouterOS\n") do={
$LogPrint warning $0 ("Removing dummy. Typo on installation?");
/system/script/remove $Script;
:continue;
}
:if ([ :len ($ScriptInfo->"base-url") ] = 0 && [ :len ($ScriptInfo->"url-suffix") ] = 0 && \
[ :convert transform=md5 to=hex [ :tolf ($ScriptVal->"source") ] ] = $CheckSum) do={
$LogPrint debug $0 ("Checksum for script '" . $ScriptVal->"name" . "' matches, ignoring.");
:error true;
[ :len $CheckSum ] = 0) do={
$LogPrintOnce warning $0 \
("Added the script manually? Skip updates with 'ignore=true' in comment.");
}
:continue;
}
:if ([ :len ($ScriptInfo->"certificate") ] > 0) do={
:if ([ $CertificateAvailable ($ScriptInfo->"certificate") "fetch" ] = false) do={
$LogPrint warning $0 ("Downloading certificate failed, trying without.");
}
}
:if ([ :len $SourceNew ] = 0) do={
$LogPrint debug $0 ("No update for script '" . $ScriptVal->"name" . "'.");
:continue;
}
:onerror Err {
:local BaseUrl [ $EitherOr ($ScriptInfo->"base-url") $ScriptUpdatesBaseUrl ];
:local UrlSuffix [ $EitherOr ($ScriptInfo->"url-suffix") $ScriptUpdatesUrlSuffix ];
:local Url ($BaseUrl . $ScriptVal->"name" . ".rsc" . $UrlSuffix);
$LogPrint debug $0 ("Fetching script '" . $ScriptVal->"name" . "' from url: " . $Url);
:local Result [ /tool/fetch check-certificate=yes-without-crl \
http-header-field=({ [ $FetchUserAgentStr $0 ] }) $Url output=user as-value ];
:if ($Result->"status" = "finished") do={
:set SourceNew [ :tolf ($Result->"data") ];
}
} do={
$LogPrint warning $0 ("Failed fetching script '" . $ScriptVal->"name" . "': " . $Err);
:if ($Err != "Fetch failed with status 404") do={
:error false;
}
:local SourceCRLF [ :tocrlf $SourceNew ];
:if ($SourceNew = $ScriptVal->"source" || $SourceCRLF = $ScriptVal->"source") do={
$LogPrint debug $0 ("Script '" . $ScriptVal->"name" . "' did not change.");
:continue;
}
:if ($ScriptVal->"source" = "#!rsc by RouterOS\n") do={
$LogPrint warning $0 ("Removing dummy. Typo on installation?");
/system/script/remove $Script;
:error false;
}
:if ([ :len ($ScriptInfo->"base-url") ] = 0 && [ :len ($ScriptInfo->"url-suffix") ] = 0 && \
[ :len $CheckSum ] = 0) do={
$LogPrintOnce warning $0 \
("Added the script manually? Skip updates with 'ignore=true' in comment.");
}
:error false;
}
:if ([ :pick $SourceNew 0 18 ] != "#!rsc by RouterOS\n") do={
$LogPrint warning $0 ("Looks like new script '" . $ScriptVal->"name" . \
"' is not valid (missing shebang). Ignoring!");
:continue;
}
:if ([ :len $SourceNew ] = 0) do={
$LogPrint debug $0 ("No update for script '" . $ScriptVal->"name" . "'.");
:error false;
}
:local RequiredROS ([ $ParseKeyValueStore [ $Grep $SourceNew ("\23 requires RouterOS, ") ] ]->"version");
:if ([ $RequiredRouterOS $0 [ $EitherOr $RequiredROS "0.0" ] false ] = false) do={
$LogPrintOnce warning $0 ("The script '" . $ScriptVal->"name" . "' requires RouterOS " . \
$RequiredROS . ", which is not met by your installation. Ignoring!");
:continue;
}
:local SourceCRLF [ :tocrlf $SourceNew ];
:if ($SourceNew = $ScriptVal->"source" || $SourceCRLF = $ScriptVal->"source") do={
$LogPrint debug $0 ("Script '" . $ScriptVal->"name" . "' did not change.");
:error false;
:local RequiredDM [ $ParseKeyValueStore [ $Grep $SourceNew ("\23 requires device-mode, ") ] ];
:local MissingDM ({});
:foreach Feature,Value in=$RequiredDM do={
:if ([ :typeof ($DeviceMode->$Feature) ] = "bool" && ($DeviceMode->$Feature) = false) do={
:set MissingDM ($MissingDM, $Feature);
}
}
:if ([ :len $MissingDM ] > 0) do={
$LogPrintOnce warning $0 ("The script '" . $ScriptVal->"name" . "' requires disabled " . \
"device-mode features (" . [ :tostr $MissingDM ] . "). Ignoring!");
:continue;
}
:if ([ :pick $SourceNew 0 18 ] != "#!rsc by RouterOS\n") do={
$LogPrint warning $0 ("Looks like new script '" . $ScriptVal->"name" . \
"' is not valid (missing shebang). Ignoring!");
:error false;
}
:if ([ $ValidateSyntax $SourceNew ] = false) do={
$LogPrint warning $0 ("Syntax validation for script '" . $ScriptVal->"name" . "' failed! Ignoring!");
:continue;
}
:local RequiredROS ([ $ParseKeyValueStore [ $Grep $SourceNew ("\23 requires RouterOS, ") ] ]->"version");
:if ([ $RequiredRouterOS $0 [ $EitherOr $RequiredROS "0.0" ] false ] = false) do={
$LogPrintOnce warning $0 ("The script '" . $ScriptVal->"name" . "' requires RouterOS " . \
$RequiredROS . ", which is not met by your installation. Ignoring!");
:error false;
}
:local RequiredDM [ $ParseKeyValueStore [ $Grep $SourceNew ("\23 requires device-mode, ") ] ];
:local MissingDM ({});
:foreach Feature,Value in=$RequiredDM do={
:if ([ :typeof ($DeviceMode->$Feature) ] = "bool" && ($DeviceMode->$Feature) = false) do={
:set MissingDM ($MissingDM, $Feature);
}
}
:if ([ :len $MissingDM ] > 0) do={
$LogPrintOnce warning $0 ("The script '" . $ScriptVal->"name" . "' requires disabled " . \
"device-mode features (" . [ :tostr $MissingDM ] . "). Ignoring!");
:error false;
}
:if ([ $ValidateSyntax $SourceNew ] = false) do={
$LogPrint warning $0 ("Syntax validation for script '" . $ScriptVal->"name" . "' failed! Ignoring!");
:error false;
}
$LogPrint info $0 ("Updating script: " . $ScriptVal->"name");
/system/script/set owner=($ScriptVal->"name") \
source=[ $IfThenElse ($ScriptUpdatesCRLF = true) $SourceCRLF $SourceNew ] $Script;
:if ($ScriptVal->"name" = "global-config" || \
$ScriptVal->"name" = "global-functions" || \
$ScriptVal->"name" ~ ("^(global-functions\\.d|mod)/.")) do={
:set ReloadGlobal true;
}
} on-error={ }
$LogPrint info $0 ("Updating script: " . $ScriptVal->"name");
/system/script/set owner=($ScriptVal->"name") \
source=[ $IfThenElse ($ScriptUpdatesCRLF = true) $SourceCRLF $SourceNew ] $Script;
:if ($ScriptVal->"name" = "global-config" || \
$ScriptVal->"name" = "global-functions" || \
$ScriptVal->"name" ~ ("^(global-functions\\.d|mod)/.")) do={
:set ReloadGlobal true;
}
}
:if ($ReloadGlobal = true) do={

View file

@ -115,7 +115,6 @@
}
:if ($Trusted = true) do={
:local Done false;
:if ($Command = "?") do={
$LogPrint info $ScriptName ("Sending notice for update " . $UpdateID . ".");
$SendTelegram2 ({ origin=$ScriptName; chatid=($Chat->"id"); silent=true; \
@ -123,9 +122,9 @@
subject=([ $SymbolForNotification "speech-balloon" ] . "Telegram Chat"); \
message=([ $IfThenElse ([ :len ($From->"first_name") ] > 0) ("Hello " . ($From->"first_name") . "!\n\n") ] . \
"Online" . [ $IfThenElse $TelegramChatActive " (and active!)" ] . ", awaiting your commands!") });
:set Done true;
:continue;
}
:if ($Done = false && [ :pick $Command 0 1 ] = "!") do={
:if ([ :pick $Command 0 1 ] = "!") do={
:if ($Command ~ ("^! *(" . [ $EscapeForRegEx $Identity ] . "|@" . $TelegramChatGroups . ")\$")) do={
:set TelegramChatActive true;
} else={
@ -133,9 +132,9 @@
}
$LogPrint info $ScriptName ("Now " . [ $IfThenElse $TelegramChatActive "active" "passive" ] . \
" from update " . $UpdateID . "!");
:set Done true;
:continue;
}
:if ($Done = false && ($IsMyReply = 1 || ($IsAnyReply = false && \
:if (($IsMyReply = 1 || ($IsAnyReply = false && \
$TelegramChatActive = true)) && [ :len $Command ] > 0) do={
:if ([ $ValidateSyntax $Command ] = true) do={
:local State "";