2020-09-18 09:00:27 +00:00
|
|
|
#!rsc by RouterOS
|
2018-10-09 11:12:08 +00:00
|
|
|
# RouterOS script: global-functions
|
2023-01-02 22:33:49 +00:00
|
|
|
# Copyright (c) 2013-2023 Christian Hesse <mail@eworm.de>
|
2019-09-12 11:48:46 +00:00
|
|
|
# Michael Gisbers <michael@gisbers.de>
|
2020-06-19 20:17:42 +00:00
|
|
|
# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md
|
2018-10-09 11:12:08 +00:00
|
|
|
#
|
2023-01-12 22:52:57 +00:00
|
|
|
# requires RouterOS, version=7.7
|
2023-01-19 21:50:51 +00:00
|
|
|
#
|
2023-03-07 09:57:42 +00:00
|
|
|
# WARNING: If you find this stripped version of global-functions
|
|
|
|
# on your Router something went wrong and migration failed. To
|
|
|
|
# recover run this function: $RouterOSScriptsRecover
|
2022-04-28 08:11:00 +00:00
|
|
|
|
2019-01-03 14:36:26 +00:00
|
|
|
# expected configuration version
|
2023-03-07 09:57:42 +00:00
|
|
|
:global ExpectedConfigVersion 95;
|
2019-01-03 14:36:26 +00:00
|
|
|
|
2019-12-10 13:45:35 +00:00
|
|
|
# global functions
|
2023-03-07 09:57:42 +00:00
|
|
|
:global RouterOSScriptsRecover;
|
2020-01-29 20:38:17 +00:00
|
|
|
:global ScriptInstallUpdate;
|
2020-03-20 07:44:24 +00:00
|
|
|
|
2023-03-07 09:57:42 +00:00
|
|
|
# recover from failed migration
|
|
|
|
:set RouterOSScriptsRecover do={
|
|
|
|
:global ScriptInstallUpdate;
|
2022-12-13 14:30:24 +00:00
|
|
|
|
2023-03-07 09:57:42 +00:00
|
|
|
:foreach Script in={ "global-config"; "global-functions" } do={
|
|
|
|
/system/script/set name=$Script source=([ /tool/fetch check-certificate=yes-without-crl ("https://git.eworm.de/cgit/routeros-scripts/plain/" . $Script . ".rsc") output=user as-value]->"data");
|
|
|
|
/system/script/run $Script;
|
2020-03-20 07:44:24 +00:00
|
|
|
}
|
|
|
|
|
2023-03-07 09:57:42 +00:00
|
|
|
$ScriptInstallUpdate;
|
2019-09-12 11:45:44 +00:00
|
|
|
}
|
2020-01-29 20:38:17 +00:00
|
|
|
|
|
|
|
# install new scripts, update existing scripts
|
|
|
|
:set ScriptInstallUpdate do={
|
2022-04-26 12:29:46 +00:00
|
|
|
:local Scripts [ :toarray $1 ];
|
|
|
|
:local NewComment [ :tostr $2 ];
|
2020-01-29 20:38:17 +00:00
|
|
|
|
2020-03-23 11:21:38 +00:00
|
|
|
:global ExpectedConfigVersion;
|
|
|
|
:global Identity;
|
|
|
|
:global IDonate;
|
2022-07-06 10:54:40 +00:00
|
|
|
:global NoNewsAndChangesNotification;
|
2021-02-25 11:27:20 +00:00
|
|
|
:global NotificationsWithSymbols;
|
2020-03-23 11:21:38 +00:00
|
|
|
:global ScriptUpdatesBaseUrl;
|
|
|
|
:global ScriptUpdatesFetch;
|
|
|
|
:global ScriptUpdatesUrlSuffix;
|
|
|
|
|
2020-12-18 16:04:22 +00:00
|
|
|
:global CertificateAvailable;
|
2023-01-19 21:43:03 +00:00
|
|
|
:global EitherOr;
|
|
|
|
:global Grep;
|
2021-02-25 11:27:20 +00:00
|
|
|
:global IfThenElse;
|
2021-02-22 14:14:10 +00:00
|
|
|
:global LogPrintExit2;
|
2020-07-01 21:55:52 +00:00
|
|
|
:global ParseKeyValueStore;
|
2023-01-19 21:43:03 +00:00
|
|
|
:global RequiredRouterOS;
|
2021-04-27 18:37:33 +00:00
|
|
|
:global SendNotification2;
|
2020-07-17 09:40:24 +00:00
|
|
|
:global SymbolForNotification;
|
2021-02-26 13:44:54 +00:00
|
|
|
:global ValidateSyntax;
|
2020-03-23 11:21:38 +00:00
|
|
|
|
2020-12-18 16:04:22 +00:00
|
|
|
:if ([ $CertificateAvailable "R3" ] = false) do={
|
2021-02-22 14:14:10 +00:00
|
|
|
$LogPrintExit2 warning $0 ("Downloading certificate failed, trying without.") false;
|
2020-12-18 16:04:22 +00:00
|
|
|
}
|
|
|
|
|
2022-09-09 12:02:02 +00:00
|
|
|
:if ([ $CertificateAvailable "E1" ] = false) do={
|
|
|
|
$LogPrintExit2 warning $0 ("Downloading certificate failed, trying without.") false;
|
|
|
|
}
|
|
|
|
|
2020-01-29 20:38:17 +00:00
|
|
|
:foreach Script in=$Scripts do={
|
2022-05-10 12:07:11 +00:00
|
|
|
:if ([ :len [ /system/script/find where name=$Script ] ] = 0) do={
|
2021-02-22 14:14:10 +00:00
|
|
|
$LogPrintExit2 info $0 ("Adding new script: " . $Script) false;
|
2022-05-10 12:07:11 +00:00
|
|
|
/system/script/add name=$Script owner=$Script source="#!rsc by RouterOS\n" comment=$NewComment;
|
2020-01-29 20:38:17 +00:00
|
|
|
}
|
|
|
|
}
|
2020-03-23 11:21:38 +00:00
|
|
|
|
2021-03-04 11:06:47 +00:00
|
|
|
:local ExpectedConfigVersionBefore $ExpectedConfigVersion;
|
2021-05-31 08:04:45 +00:00
|
|
|
:local ReloadGlobalFunctions false;
|
2021-06-02 21:51:11 +00:00
|
|
|
:local ReloadGlobalConfig false;
|
2021-01-21 10:15:49 +00:00
|
|
|
|
2022-05-10 12:07:11 +00:00
|
|
|
:foreach Script in=[ /system/script/find where source~"^#!rsc by RouterOS\n" ] do={
|
|
|
|
:local ScriptVal [ /system/script/get $Script ];
|
|
|
|
:local ScriptFile [ /file/find where name=("script-updates/" . $ScriptVal->"name") ];
|
2020-03-23 11:21:38 +00:00
|
|
|
:local SourceNew;
|
|
|
|
:if ([ :len $ScriptFile ] > 0) do={
|
2023-02-07 20:20:49 +00:00
|
|
|
:set SourceNew [ /file/get $ScriptFile contents ];
|
2022-05-10 12:07:11 +00:00
|
|
|
/file/remove $ScriptFile;
|
2020-03-23 11:21:38 +00:00
|
|
|
}
|
|
|
|
|
2022-05-10 12:07:11 +00:00
|
|
|
:foreach Scheduler in=[ /system/scheduler/find where on-event~("\\b" . $ScriptVal->"name" . "\\b") ] do={
|
|
|
|
:local SchedulerVal [ /system/scheduler/get $Scheduler ];
|
2020-03-23 11:21:38 +00:00
|
|
|
:if ($ScriptVal->"policy" != $SchedulerVal->"policy") do={
|
2022-01-20 21:11:30 +00:00
|
|
|
$LogPrintExit2 warning $0 ("Policies differ for script '" . $ScriptVal->"name" . \
|
|
|
|
"' and its scheduler '" . $SchedulerVal->"name" . "'!") false;
|
2020-03-23 11:21:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
:if ([ :len $SourceNew ] = 0 && $ScriptUpdatesFetch = true) do={
|
2020-07-01 21:55:52 +00:00
|
|
|
:local Comment [ $ParseKeyValueStore ($ScriptVal->"comment") ];
|
2020-12-20 22:30:18 +00:00
|
|
|
:if (!($Comment->"ignore" = true)) do={
|
2020-03-23 11:21:38 +00:00
|
|
|
:do {
|
2020-07-01 22:03:21 +00:00
|
|
|
:local BaseUrl $ScriptUpdatesBaseUrl;
|
|
|
|
:local UrlSuffix $ScriptUpdatesUrlSuffix;
|
|
|
|
:if ([ :typeof ($Comment->"base-url") ] = "str") do={ :set BaseUrl ($Comment->"base-url"); }
|
|
|
|
:if ([ :typeof ($Comment->"url-suffix") ] = "str") do={ :set UrlSuffix ($Comment->"url-suffix"); }
|
2023-03-07 09:57:42 +00:00
|
|
|
:local Url ($BaseUrl . $ScriptVal->"name" . ".rsc" . $UrlSuffix);
|
2020-07-01 22:03:21 +00:00
|
|
|
|
2022-01-20 21:05:05 +00:00
|
|
|
$LogPrintExit2 debug $0 ("Fetching script '" . $ScriptVal->"name" . "' from url: " . $Url) false;
|
2022-05-10 12:07:11 +00:00
|
|
|
:local Result [ /tool/fetch check-certificate=yes-without-crl $Url output=user as-value ];
|
2020-03-23 11:21:38 +00:00
|
|
|
:if ($Result->"status" = "finished") do={
|
|
|
|
:set SourceNew ($Result->"data");
|
|
|
|
}
|
|
|
|
} on-error={
|
2022-06-28 19:05:50 +00:00
|
|
|
:if ($ScriptVal->"source" = "#!rsc by RouterOS\n") do={
|
|
|
|
$LogPrintExit2 warning $0 ("Failed fetching script '" . $ScriptVal->"name" . \
|
|
|
|
"', removing dummy. Typo on installation?") false;
|
|
|
|
/system/script/remove $Script;
|
|
|
|
} else={
|
|
|
|
$LogPrintExit2 warning $0 ("Failed fetching script '" . $ScriptVal->"name" . "'!") false;
|
|
|
|
}
|
2020-03-23 11:21:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
:if ([ :len $SourceNew ] > 0) do={
|
2021-02-25 15:31:19 +00:00
|
|
|
:if ($SourceNew != $ScriptVal->"source") do={
|
|
|
|
:if ([ :pick $SourceNew 0 18 ] = "#!rsc by RouterOS\n") do={
|
2023-01-19 21:43:03 +00:00
|
|
|
:local Required ([ $ParseKeyValueStore [ $Grep $SourceNew "# requires RouterOS, " ] ]->"version");
|
|
|
|
:if ([ $RequiredRouterOS $0 [ $EitherOr $Required "0.0" ] false ] = true) do={
|
|
|
|
:if ([ $ValidateSyntax $SourceNew ] = true) do={
|
|
|
|
$LogPrintExit2 info $0 ("Updating script: " . $ScriptVal->"name") false;
|
|
|
|
/system/script/set owner=($ScriptVal->"name") source=$SourceNew $Script;
|
|
|
|
:if ($ScriptVal->"name" = "global-config") do={
|
|
|
|
:set ReloadGlobalConfig true;
|
|
|
|
}
|
|
|
|
:if ($ScriptVal->"name" = "global-functions" || $ScriptVal->"name" ~ ("^mod/.")) do={
|
|
|
|
:set ReloadGlobalFunctions true;
|
|
|
|
}
|
|
|
|
} else={
|
|
|
|
$LogPrintExit2 warning $0 ("Syntax validation for script '" . $ScriptVal->"name" . \
|
|
|
|
"' failed! Ignoring!") false;
|
2021-01-03 20:21:17 +00:00
|
|
|
}
|
2021-02-25 15:36:44 +00:00
|
|
|
} else={
|
2023-01-19 21:43:03 +00:00
|
|
|
$LogPrintExit2 warning $0 ("The script '" . $ScriptVal->"name" . "' requires RouterOS " . \
|
|
|
|
$Required . ", which is not met by your installation. Ignoring!") false;
|
2020-03-23 11:21:38 +00:00
|
|
|
}
|
|
|
|
} else={
|
2022-01-20 21:11:30 +00:00
|
|
|
$LogPrintExit2 warning $0 ("Looks like new script '" . $ScriptVal->"name" . \
|
|
|
|
"' is not valid (missing shebang). Ignoring!") false;
|
2020-03-23 11:21:38 +00:00
|
|
|
}
|
|
|
|
} else={
|
2022-01-20 21:11:30 +00:00
|
|
|
$LogPrintExit2 debug $0 ("Script '" . $ScriptVal->"name" . "' did not change.") false;
|
2020-03-23 11:21:38 +00:00
|
|
|
}
|
|
|
|
} else={
|
2022-01-20 21:11:30 +00:00
|
|
|
$LogPrintExit2 debug $0 ("No update for script '" . $ScriptVal->"name" . "'.") false;
|
2020-03-23 11:21:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-31 08:04:45 +00:00
|
|
|
:if ($ReloadGlobalFunctions = true) do={
|
|
|
|
$LogPrintExit2 info $0 ("Reloading global functions.") false;
|
|
|
|
:do {
|
2022-05-10 12:07:11 +00:00
|
|
|
/system/script/run global-functions;
|
2021-05-31 08:04:45 +00:00
|
|
|
} on-error={
|
|
|
|
$LogPrintExit2 error $0 ("Reloading global functions failed!") false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-02 21:51:11 +00:00
|
|
|
:if ($ReloadGlobalConfig = true) do={
|
2021-12-07 14:40:14 +00:00
|
|
|
$LogPrintExit2 info $0 ("Reloading global configuration.") false;
|
2021-06-02 21:51:11 +00:00
|
|
|
:do {
|
2022-05-10 12:07:11 +00:00
|
|
|
/system/script/run global-config;
|
2021-06-02 21:51:11 +00:00
|
|
|
} on-error={
|
2021-12-07 14:40:14 +00:00
|
|
|
$LogPrintExit2 error $0 ("Reloading global configuration failed!" . \
|
2023-06-26 09:14:55 +00:00
|
|
|
" Syntax error or missing overlay?") false;
|
2021-06-02 21:51:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-12 07:17:48 +00:00
|
|
|
:if ($ExpectedConfigVersionBefore > $ExpectedConfigVersion) do={
|
|
|
|
$LogPrintExit2 warning $0 ("The configuration version decreased from " . \
|
|
|
|
$ExpectedConfigVersionBefore . " to " . $ExpectedConfigVersion . \
|
|
|
|
". Installed an older version?") false;
|
|
|
|
}
|
|
|
|
|
|
|
|
:if ($ExpectedConfigVersionBefore < $ExpectedConfigVersion) do={
|
2020-03-23 11:21:38 +00:00
|
|
|
:global GlobalConfigChanges;
|
2020-12-18 16:50:37 +00:00
|
|
|
:global GlobalConfigMigration;
|
2020-03-23 11:21:38 +00:00
|
|
|
:local ChangeLogCode;
|
|
|
|
|
|
|
|
:do {
|
2023-03-07 09:57:42 +00:00
|
|
|
:local Url ($ScriptUpdatesBaseUrl . "news-and-changes.rsc" . $ScriptUpdatesUrlSuffix);
|
2022-01-20 21:05:05 +00:00
|
|
|
$LogPrintExit2 debug $0 ("Fetching news, changes and migration: " . $Url) false;
|
2022-05-10 12:07:11 +00:00
|
|
|
:local Result [ /tool/fetch check-certificate=yes-without-crl $Url output=user as-value ];
|
2020-03-23 11:21:38 +00:00
|
|
|
:if ($Result->"status" = "finished") do={
|
|
|
|
:set ChangeLogCode ($Result->"data");
|
|
|
|
}
|
|
|
|
} on-error={
|
2021-03-04 11:06:47 +00:00
|
|
|
$LogPrintExit2 warning $0 ("Failed fetching news, changes and migration!") false;
|
2020-03-23 11:21:38 +00:00
|
|
|
}
|
|
|
|
|
2021-02-26 13:52:50 +00:00
|
|
|
:if ([ :len $ChangeLogCode ] > 0) do={
|
|
|
|
:if ([ $ValidateSyntax $ChangeLogCode ] = true) do={
|
2021-07-09 20:04:15 +00:00
|
|
|
:do {
|
|
|
|
[ :parse $ChangeLogCode ];
|
|
|
|
} on-error={
|
|
|
|
$LogPrintExit2 warning $0 ("The changelog failed to run!") false;
|
|
|
|
}
|
2021-03-04 11:06:47 +00:00
|
|
|
} else={
|
|
|
|
$LogPrintExit2 warning $0 ("The changelog failed syntax validation!") false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
:if ([ :len $GlobalConfigMigration ] > 0) do={
|
|
|
|
:for I from=($ExpectedConfigVersionBefore + 1) to=$ExpectedConfigVersion do={
|
|
|
|
:local Migration ($GlobalConfigMigration->[ :tostr $I ]);
|
|
|
|
:if ([ :typeof $Migration ] = "str") do={
|
|
|
|
:if ([ $ValidateSyntax $Migration ] = true) do={
|
|
|
|
$LogPrintExit2 info $0 ("Applying migration for change " . $I . ": " . $Migration) false;
|
2021-07-09 10:30:35 +00:00
|
|
|
:do {
|
|
|
|
[ :parse $Migration ];
|
|
|
|
} on-error={
|
|
|
|
$LogPrintExit2 warning $0 ("Migration code for change " . $I . " failed to run!") false;
|
|
|
|
}
|
2021-03-04 11:06:47 +00:00
|
|
|
} else={
|
|
|
|
$LogPrintExit2 warning $0 ("Migration code for change " . $I . " failed syntax validation!") false;
|
2021-02-26 13:52:50 +00:00
|
|
|
}
|
|
|
|
}
|
2021-03-04 11:06:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-28 06:44:05 +00:00
|
|
|
:local NotificationMessage ("The configuration version on " . $Identity . " increased " . \
|
|
|
|
"to " . $ExpectedConfigVersion . ", current configuration may need modification. " . \
|
|
|
|
"Please review and update global-config-overlay, then re-run global-config.");
|
|
|
|
$LogPrintExit2 info $0 ($NotificationMessage) false;
|
|
|
|
|
|
|
|
:if ([ :len $GlobalConfigChanges ] > 0) do={
|
|
|
|
:set NotificationMessage ($NotificationMessage . "\n\nChanges:");
|
|
|
|
:for I from=($ExpectedConfigVersionBefore + 1) to=$ExpectedConfigVersion do={
|
|
|
|
:local Change ($GlobalConfigChanges->[ :tostr $I ]);
|
|
|
|
:set NotificationMessage ($NotificationMessage . "\n " . \
|
|
|
|
[ $IfThenElse ($NotificationsWithSymbols = true) ("\E2\97\8F") "*" ] . " " . $Change);
|
|
|
|
$LogPrintExit2 info $0 ("Change " . $I . ": " . $Change) false;
|
2021-03-04 11:06:47 +00:00
|
|
|
}
|
2022-09-28 06:44:05 +00:00
|
|
|
} else={
|
|
|
|
:set NotificationMessage ($NotificationMessage . "\n\nNews and changes are not available.");
|
|
|
|
}
|
2021-03-04 11:06:47 +00:00
|
|
|
|
2022-09-28 06:44:05 +00:00
|
|
|
:if ($NoNewsAndChangesNotification != true) do={
|
2021-03-04 11:06:47 +00:00
|
|
|
:local Link;
|
|
|
|
:if ($IDonate != true) do={
|
2021-02-26 13:52:50 +00:00
|
|
|
:set NotificationMessage ($NotificationMessage . \
|
2021-03-04 11:06:47 +00:00
|
|
|
"\n\n==== donation hint ====\n" . \
|
|
|
|
"This project is developed in private spare time and usage is " . \
|
|
|
|
"free of charge for you. If you like the scripts and think this is " . \
|
|
|
|
"of value for you or your business please consider a donation.");
|
|
|
|
:set Link "https://git.eworm.de/cgit/routeros-scripts/about/#donate";
|
2021-02-26 13:52:50 +00:00
|
|
|
}
|
|
|
|
|
2021-04-27 19:38:37 +00:00
|
|
|
$SendNotification2 ({ origin=$0; \
|
|
|
|
subject=([ $SymbolForNotification "pushpin" ] . "News and configuration changes"); \
|
|
|
|
message=$NotificationMessage; link=$Link });
|
2020-03-23 11:21:38 +00:00
|
|
|
}
|
|
|
|
|
2021-03-04 11:06:47 +00:00
|
|
|
:set GlobalConfigChanges;
|
|
|
|
:set GlobalConfigMigration;
|
2020-03-23 11:21:38 +00:00
|
|
|
}
|
2020-01-29 20:38:17 +00:00
|
|
|
}
|