diff --git a/CONTRIBUTIONS.md b/CONTRIBUTIONS.md index 33f82f95..a427aedb 100644 --- a/CONTRIBUTIONS.md +++ b/CONTRIBUTIONS.md @@ -7,12 +7,14 @@ Thanks a lot for your contributions! ## Patches -These persons contributed code. See the git history for details! +These persons contributed code or documentation. See the git history +for details! * [Ben Harris](mailto:mail@bharr.is) (@bharrisau) * [Daniel Ziegenberg](mailto:daniel@ziegenberg.at) (@ziegenberg) * [Michael Gisbers](mailto:michael@gisbers.de) (@mgisbers) * [netztrip](mailto:dave-tvg@netztrip.de) (@netztrip) +* [Stefan Müller](mailto:stefan.mueller.83@gmail.com) (@PackElend) ## Donations @@ -22,6 +24,8 @@ Add yourself to the list, * Abdul Mannan Abbasi * Andrew Cox * Christoph Boss (@Kampfwurst) +* Devin Dean (@dd2594gh) +* Evaldo Gardenal * Klaus Michael Rübsam * Linux-Schmie.de Michael Gisbers * Manuel Kuhn diff --git a/INITIAL-COMMANDS.md b/INITIAL-COMMANDS.md index 9a8a1293..33e424ab 100644 --- a/INITIAL-COMMANDS.md +++ b/INITIAL-COMMANDS.md @@ -3,17 +3,13 @@ Initial commands [◀ Go back to main README](README.md) -These command are inteneded for initial setup. If you are not aware of the -procedure please follow [the long way in detail](README.md#the-long-way-in-detail). +> ⚠️ **Warning**: These commands are inteneded for initial setup. If you are +> not aware of the procedure please follow +> [the long way in detail](README.md#the-long-way-in-detail). -One extra step is required if you run RouterOS v6: - - :global ScriptUpdatesUrlSuffix "\?h=routeros-v6"; - -Then run the complete base installation: +Run the complete base installation: { - :global ScriptUpdatesUrlSuffix; / tool fetch "https://git.eworm.de/cgit/routeros-scripts/plain/certs/R3.pem" dst-path="letsencrypt-R3.pem" as-value; :delay 1s; / certificate import file-name=letsencrypt-R3.pem passphrase=""; @@ -21,8 +17,9 @@ Then run the complete base installation: :error "Something is wrong with your certificates!"; }; / file remove "letsencrypt-R3.pem"; + :delay 1s; :foreach Script in={ "global-config"; "global-config-overlay"; "global-functions" } do={ - / system script add name=$Script source=([ / tool fetch check-certificate=yes-without-crl ("https://git.eworm.de/cgit/routeros-scripts/plain/" . $Script . $ScriptUpdatesUrlSuffix) output=user as-value]->"data"); + / system script add name=$Script source=([ / tool fetch check-certificate=yes-without-crl ("https://git.eworm.de/cgit/routeros-scripts/plain/" . $Script . "\?h=routeros-v6") output=user as-value]->"data"); }; / system script { run global-config; run global-functions; }; / system scheduler add name="global-scripts" start-time=startup on-event="/ system script { run global-config; run global-functions; }"; diff --git a/Makefile b/Makefile index b07d27de..9f21255a 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ TEMPLATE = $(wildcard *.template) CAPSMAN = $(TEMPLATE:.template=.capsman) LOCAL = $(TEMPLATE:.template=.local) -MARKDOWN = $(wildcard *.md) $(wildcard doc/*.md) +MARKDOWN = $(wildcard *.md doc/*.md doc/mod/*.md) HTML = $(MARKDOWN:.md=.html) all: $(CAPSMAN) $(LOCAL) $(HTML) diff --git a/README.d/12-install-custom-script.avif b/README.d/12-install-custom-script.avif new file mode 100644 index 00000000..fb536061 Binary files /dev/null and b/README.d/12-install-custom-script.avif differ diff --git a/README.d/hello-world.rsc b/README.d/hello-world.rsc new file mode 100644 index 00000000..17ec5752 --- /dev/null +++ b/README.d/hello-world.rsc @@ -0,0 +1,3 @@ +#!rsc by RouterOS + +:put ("Hello World from " . [ / system identity get name ] . "!"); diff --git a/README.md b/README.md index 990aef9d..7b01c545 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,8 @@ RouterOS script distribution](https://www.youtube.com/watch?v=B9neG3oAhcY) including demonstation recorded live at [MUM Europe 2019](https://mum.mikrotik.com/2019/EU/) in Vienna. -*Be warned!* Some details changed. So see the presentation, then follow -the steps below for up-to-date commands. +> ⚠️ **Warning**: Some details changed. So see the presentation, then follow +> the steps below for up-to-date commands. ### The long way in detail @@ -82,14 +82,9 @@ All following commands will verify the server certificate. For validity the certificate's lifetime is checked with local time, so make sure the device's date and time is set correctly! -One extra step is required if you run RouterOS v6: - - :global ScriptUpdatesUrlSuffix "\?h=routeros-v6"; - Now let's download the main scripts and add them in configuration on the fly. - :global ScriptUpdatesUrlSuffix; - :foreach Script in={ "global-config"; "global-config-overlay"; "global-functions" } do={ / system script add name=$Script source=([ / tool fetch check-certificate=yes-without-crl ("https://git.eworm.de/cgit/routeros-scripts/plain/" . $Script . $ScriptUpdatesUrlSuffix) output=user as-value]->"data"); }; + :foreach Script in={ "global-config"; "global-config-overlay"; "global-functions" } do={ / system script add name=$Script source=([ / tool fetch check-certificate=yes-without-crl ("https://git.eworm.de/cgit/routeros-scripts/plain/" . $Script . "\?h=routeros-v6") output=user as-value]->"data"); }; ![screenshot: import scripts](README.d/04-import-scripts.avif) @@ -118,10 +113,8 @@ to be updated automatically! ### Changes for RouterOS v6 -RouterOS v6 will become deprecated at some time in the future, but to date -it is still the default for these scripts (in branch `main`). This will -change however, so if you want to stay with RouterOS v6 for some time add -these lines to your `global-config-overlay`, if missing: +Let's consider RouterOS v6 being legacy. If you want to stay with RouterOS +v6 for some time add these lines to your `global-config-overlay`, if missing: # Use branch routeros-v6 with RouterOS v6: :global ScriptUpdatesUrlSuffix "\?h=routeros-v6"; @@ -130,15 +123,8 @@ Then reload the configuration. ### Changes for RouterOS v7 -RouterOS v7 is developed in paralled to RouterOS v6. The former brings some -shiny new features, the latter provides proven stability. - -The changes require incompatible changes to scripts, so these changes go to -a separate branch. If you decide to run RouterOS v7 please switch to branch -`routeros-v7` by adding these lines to your `global-config-overlay`: - - # Use branch routeros-v7 with RouterOS v7: - :global ScriptUpdatesUrlSuffix "\?h=routeros-v7"; +RouterOS v7 is the future, and default branch `main` expects it. Just drop +`$ScriptUpdatesUrlSuffix` from your `global-config-overlay` to use that. Then reload the configuration and continue below to update scripts. @@ -192,6 +178,7 @@ Available scripts * [Find and remove access list duplicates](doc/accesslist-duplicates.md) * [Upload backup to Mikrotik cloud](doc/backup-cloud.md) * [Send backup via e-mail](doc/backup-email.md) +* [Save configuration to fallback partition](doc/backup-partition.md) * [Upload backup to server](doc/backup-upload.md) * [Download packages for CAP upgrade from CAPsMAN](doc/capsman-download-packages.md) * [Run rolling CAP upgrades from CAPsMAN](doc/capsman-rolling-upgrade.md) @@ -204,6 +191,7 @@ Available scripts * [Use wireless network with daily psk](doc/daily-psk.md) * [Comment DHCP leases with info from access list](doc/dhcp-lease-comment.md) * [Create DNS records for DHCP leases](doc/dhcp-to-dns.md) +* [Automatically upgrade firmware and reboot](doc/firmware-upgrade-reboot.md) * [Wait for global functions und modules](doc/global-wait.md) * [Send GPS position to server](doc/gps-track.md) * [Use WPA2 network with hotspot credentials](doc/hotspot-to-wpa.md) @@ -238,6 +226,34 @@ Available modules * [Manage ports in bridge](doc/mod/bridge-port-to.md) * [Manage VLANs on bridge ports](doc/mod/bridge-port-vlan.md) +* [Inspect variables](doc/mod/inspectvar.md) +* [IP address calculation](doc/mod/ipcalc.md) +* [Send notifications via Matrix](doc/mod/notification-matrix.md) +* [Send notifications via Telegram](doc/mod/notification-telegram.md) +* [Download script and run it once](doc/mod/scriptrunonce.md) + +Installing custom scripts & modules +----------------------------------- + +My scripts cover a lot of use cases, but you may have your own ones. You can +still use my scripts to manage and deploy yours, by specifying `base-url` +(and `url-suffix`) for each script. + +This will fetch and install a script `hello-world.rsc` from the given url: + + $ScriptInstallUpdate hello-world.rsc "base-url=https://git.eworm.de/cgit/routeros-scripts/plain/README.d/" + +![screenshot: install custom script](README.d/12-install-custom-script.avif) + +(Yes, the example url still belongs to the repository for easy +handling - but the url can be what ever you use.) + +For a script to be considered valid it has to begin with a *magic token*. +Have a look at [any script](README.d/hello-world.rsc) and copy the first line +without modification. + +Starting a script's name with `mod/` makes it a module and it is run +automatically by `global-functions`. Contact ------- diff --git a/accesslist-duplicates.capsman b/accesslist-duplicates.capsman index 6d2c8967..74cf3b35 100644 --- a/accesslist-duplicates.capsman +++ b/accesslist-duplicates.capsman @@ -12,7 +12,7 @@ :global GlobalFunctionsReady; :while ($GlobalFunctionsReady != true) do={ :delay 500ms; } -:local Read do={ :return; } +:global Read; :local Seen [ :toarray "" ]; :local Shown [ :toarray "" ]; diff --git a/accesslist-duplicates.local b/accesslist-duplicates.local index 24c8e29f..0aa946c0 100644 --- a/accesslist-duplicates.local +++ b/accesslist-duplicates.local @@ -12,7 +12,7 @@ :global GlobalFunctionsReady; :while ($GlobalFunctionsReady != true) do={ :delay 500ms; } -:local Read do={ :return; } +:global Read; :local Seen [ :toarray "" ]; :local Shown [ :toarray "" ]; diff --git a/accesslist-duplicates.template b/accesslist-duplicates.template index f9f44942..f1862bbf 100644 --- a/accesslist-duplicates.template +++ b/accesslist-duplicates.template @@ -13,7 +13,7 @@ :global GlobalFunctionsReady; :while ($GlobalFunctionsReady != true) do={ :delay 500ms; } -:local Read do={ :return; } +:global Read; :local Seen [ :toarray "" ]; :local Shown [ :toarray "" ]; diff --git a/backup-partition b/backup-partition new file mode 100644 index 00000000..c72c7f93 --- /dev/null +++ b/backup-partition @@ -0,0 +1,36 @@ +#!rsc by RouterOS +# RouterOS script: backup-partition +# Copyright (c) 2022 Christian Hesse +# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md +# +# provides: backup-script +# +# save configuration to fallback partition +# https://git.eworm.de/cgit/routeros-scripts/about/doc/backup-partition.md + +:local 0 "backup-partition"; +:global GlobalFunctionsReady; +:while ($GlobalFunctionsReady != true) do={ :delay 500ms; } + +:global LogPrintExit2; + +:if ([ :len [ / partitions find ] ] < 2) do={ + $LogPrintExit2 error $0 ("Device does not have a fallback partition.") true; +} + +:local ActiveRunning [ / partitions find where active running ]; + +:if ([ :len $ActiveRunning ] < 1) do={ + $LogPrintExit2 error $0 ("Device is not running from active partition.") true; +} + +:local ActiveRunningVar [ / partitions get $ActiveRunning ]; + +:do { + / partitions save-config-to ($ActiveRunningVar->"fallback-to"); + $LogPrintExit2 info $0 ("Saved configuration to partition '" . \ + ($ActiveRunningVar->"fallback-to") . "'.") false; +} on-error={ + $LogPrintExit2 error $0 ("Failed saving configuration to partition '" . \ + ($ActiveRunningVar->"fallback-to") . "'!") true; +} diff --git a/capsman-download-packages b/capsman-download-packages index 333f01b4..0eae744a 100644 --- a/capsman-download-packages +++ b/capsman-download-packages @@ -47,12 +47,39 @@ $WaitFullyConnected; :if ($File->"package-name" = "wireless@") do={ :set ($File->"package-name") "wireless"; } - :if ([ $DownloadPackage ($File->"package-name") $InstalledVersion ($File->"package-architecture") $PackagePath ] = true) do={ + :if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \ + ($File->"package-architecture") $PackagePath ] = true) do={ :set Updated true; / file remove $Package; } } +:if ([ :len [ / system logging find where topics~"error" !(topics~"!error") \ + !(topics~"!caps") action=memory !disabled !invalid ] ] < 1) do={ + $LogPrintExit2 warning $0 ("Looks like error messages for 'caps' are not sent to memory. " . \ + "Probably can not download packages automatically.") false; +} else={ + :if ($Updated = false && [ / system resource get uptime ] < 2m) do={ + $LogPrintExit2 info $0 ("No packages downloaded, yet. Delaying for logs.") false; + :delay 2m; + } +} + +:foreach Log in=[ / log find where topics=({"caps", "error"}) \ + message~("upgrade status: failed, failed to download file '.*-" . $InstalledVersion . \ + "-.*\\.npk', no such file") ] do={ + :local Message [ / log get $Log message ]; + :local Package [ :pick $Message \ + ([ :find $Message "'" ] + 1) \ + [ :find $Message ("-" . $InstalledVersion . "-") ] ]; + :local Arch [ :pick $Message \ + ([ :find $Message ("-" . $InstalledVersion . "-") ] + 2 + [ :len $InstalledVersion ]) \ + [ :find $Message ".npk" ] ]; + :if ([ $DownloadPackage $Package $InstalledVersion $Arch $PackagePath ] = true) do={ + :set Updated true; + } +} + :if ($Updated = true) do={ :if ([ :len [ / system script find where name="capsman-rolling-upgrade" ] ] > 0) do={ / system script run capsman-rolling-upgrade; diff --git a/check-lte-firmware-upgrade b/check-lte-firmware-upgrade index aef27fee..5f6bb691 100644 --- a/check-lte-firmware-upgrade +++ b/check-lte-firmware-upgrade @@ -10,37 +10,73 @@ :global GlobalFunctionsReady; :while ($GlobalFunctionsReady != true) do={ :delay 500ms; } -:global Identity; :global SentLteFirmwareUpgradeNotification; -:global CharacterReplace; -:global LogPrintExit2; -:global SendNotification2; -:global SymbolForNotification; +:if ([ :typeof $SentLteFirmwareUpgradeNotification ] != "array") do={ + :global SentLteFirmwareUpgradeNotification [ :toarray "" ]; +} + +:local CheckInterface do={ + :local Interface $1; + + :global Identity; + :global SentLteFirmwareUpgradeNotification; + + :global CharacterReplace; + :global LogPrintExit2; + :global ScriptFromTerminal; + :global SendNotification2; + :global SymbolForNotification; -:foreach Interface in=[ / interface lte find ] do={ :local IntName [ / interface lte get $Interface name ]; + :local Firmware; + :local Info; :do { - :local Firmware [ / interface lte firmware-upgrade $Interface once as-value ]; - - :if ($SentLteFirmwareUpgradeNotification = ($Firmware->"latest")) do={ - $LogPrintExit2 debug $0 ("Already sent the LTE firmware upgrade notification for version " . \ - ($Firmware->"latest") . ".") false; - } else={ - :if (($Firmware->"installed") != ($Firmware->"latest")) do={ - :local Info [ / interface lte info $Interface once as-value ]; - $SendNotification2 ({ origin=$0; \ - subject=([ $SymbolForNotification "sparkles" ] . "LTE firmware upgrade"); \ - message=("A new firmware version " . ($Firmware->"latest") . " is available for " . \ - "LTE interface " . $IntName . " on " . $Identity . ".\n\n" . \ - "Interface: " . [ $CharacterReplace ($Info->"manufacturer" . " " . $Info->"model") ("\"") "" ] . "\n" . \ - "Installed: " . ($Firmware->"installed") . "\n" . \ - "Available: " . ($Firmware->"latest")); silent=true }); - :set SentLteFirmwareUpgradeNotification ($Firmware->"latest"); - } - } + :set Firmware [ / interface lte firmware-upgrade $Interface once as-value ]; + :set Info [ / interface lte info $Interface once as-value ]; } on-error={ $LogPrintExit2 debug $0 ("Could not get latest LTE firmware version for interface " . \ $IntName . ".") false; + :return false; } + + :if (($Firmware->"installed") = ($Firmware->"latest")) do={ + :if ([ $ScriptFromTerminal "check-lte-firmware-upgrade" ] = true) do={ + $LogPrintExit2 info $0 ("No firmware upgrade available for LTE interface " . $IntName . ".") false; + } + :return true; + } + + :if ([ $ScriptFromTerminal "check-lte-firmware-upgrade" ] = true && \ + [ :len [ / system script find where name="unattended-lte-firmware-upgrade" ] ] > 0) do={ + :put ("Do you want to start unattended lte firmware upgrade for interface " . $IntName . "? [y/N]"); + :if (([ / terminal inkey timeout=60 ] % 32) = 25) do={ + / system script run unattended-lte-firmware-upgrade; + $LogPrintExit2 info $0 ("Scheduled lte firmware upgrade for interface " . $IntName . "...") false; + :return true; + } else={ + :put "Canceled..."; + } + } + + :if (($SentLteFirmwareUpgradeNotification->$IntName) = ($Firmware->"latest")) do={ + $LogPrintExit2 debug $0 ("Already sent the LTE firmware upgrade notification for version " . \ + ($Firmware->"latest") . ".") false; + :return false; + } + + $LogPrintExit2 info $0 ("A new firmware version " . ($Firmware->"latest") . " is available for " . \ + "LTE interface " . $IntName . ".") false; + $SendNotification2 ({ origin=$0; \ + subject=([ $SymbolForNotification "sparkles" ] . "LTE firmware upgrade"); \ + message=("A new firmware version " . ($Firmware->"latest") . " is available for " . \ + "LTE interface " . $IntName . " on " . $Identity . ".\n\n" . \ + "Interface: " . [ $CharacterReplace ($Info->"manufacturer" . " " . $Info->"model") ("\"") "" ] . "\n" . \ + "Installed: " . ($Firmware->"installed") . "\n" . \ + "Available: " . ($Firmware->"latest")); silent=true }); + :set ($SentLteFirmwareUpgradeNotification->$IntName) ($Firmware->"latest"); +} + +:foreach Interface in=[ / interface lte find ] do={ + $CheckInterface $Interface; } diff --git a/check-routeros-update b/check-routeros-update index 0f687a5e..8cad07ab 100644 --- a/check-routeros-update +++ b/check-routeros-update @@ -108,7 +108,7 @@ $LogPrintExit2 debug $0 ("Checking for updates...") false; :if ([ $ScriptFromTerminal $0 ] = true) do={ :put ("Do you want to install RouterOS version " . $Update->"latest-version" . "? [y/N]"); - :if (([ :terminal inkey timeout=60 ] % 32) = 25) do={ + :if (([ / terminal inkey timeout=60 ] % 32) = 25) do={ $DoUpdate; } else={ :put "Canceled..."; diff --git a/cloud-backup b/cloud-backup deleted file mode 100644 index 2c48f071..00000000 --- a/cloud-backup +++ /dev/null @@ -1,2 +0,0 @@ -#!rsc by RouterOS -# dummy for migration diff --git a/doc/accesslist-duplicates.md b/doc/accesslist-duplicates.md index e052c20a..db1e00a1 100644 --- a/doc/accesslist-duplicates.md +++ b/doc/accesslist-duplicates.md @@ -3,8 +3,8 @@ Find and remove access list duplicates [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/backup-cloud.md b/doc/backup-cloud.md index 117e4c7d..6a15688e 100644 --- a/doc/backup-cloud.md +++ b/doc/backup-cloud.md @@ -3,13 +3,19 @@ Upload backup to Mikrotik cloud [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **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 uploads [binary backup to Mikrotik cloud](https://wiki.mikrotik.com/wiki/Manual:IP/Cloud#Backup). +This script uploads +[binary backup to Mikrotik cloud](https://wiki.mikrotik.com/wiki/Manual:IP/Cloud#Backup). + +> ⚠️ **Warning**: The used command can hit errors that a script can not handle. +> This may result in script termination (where no notification is sent) or +> malfunction of fetch command (where all up- and downloads break) for some +> time. Failed notifications are queued then. ### Sample notification @@ -30,7 +36,9 @@ The configuration goes to `global-config-overlay`, these are the parameters: * `BackupPassword`: password to encrypt the backup with * `BackupRandomDelay`: delay up to amount of seconds when run from scheduler -Also notification settings are required for e-mail, matrix and/or telegram. +Also notification settings are required for e-mail, +[matrix](mod/notification-matrix.md) and/or +[telegram](mod/notification-telegram.md). Usage and invocation -------------------- @@ -47,6 +55,7 @@ See also -------- * [Send backup via e-mail](backup-email.md) +* [Save configuration to fallback partition](doc/backup-partition.md) * [Upload backup to server](backup-upload.md) --- diff --git a/doc/backup-email.md b/doc/backup-email.md index be36cb4f..9c2edb5f 100644 --- a/doc/backup-email.md +++ b/doc/backup-email.md @@ -3,8 +3,8 @@ Send backup via e-mail [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -12,7 +12,6 @@ Description This script sends binary backup (`/ system backup save`) and complete configuration export (`/ export terse`) via e-mail. - Requirements and installation ----------------------------- @@ -47,6 +46,7 @@ See also -------- * [Upload backup to Mikrotik cloud](backup-cloud.md) +* [Save configuration to fallback partition](doc/backup-partition.md) * [Upload backup to server](backup-upload.md) --- diff --git a/doc/backup-partition.md b/doc/backup-partition.md new file mode 100644 index 00000000..c31c780c --- /dev/null +++ b/doc/backup-partition.md @@ -0,0 +1,45 @@ +Save configuration to fallback partition +======================================== + +[◀ 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 saves the current configuration to fallback +[partition](https://wiki.mikrotik.com/wiki/Manual:Partitions). + +For this to work you need a device with sufficient flash storage that is +properly partitioned. + +Requirements and installation +----------------------------- + +Just install the script: + + $ScriptInstallUpdate backup-partition; + +Usage and invocation +-------------------- + +Just run the script: + + / system script run backup-partition; + +Creating a scheduler may be an option: + + / system scheduler add interval=1w name=backup-partition on-event="/ system script run backup-partition;" start-time=09:30:00; + +See also +-------- + +* [Upload backup to Mikrotik cloud](backup-cloud.md) +* [Send backup via e-mail](backup-email.md) +* [Upload backup to server](backup-upload.md) + +--- +[◀ Go back to main README](../README.md) +[▲ Go back to top](#top) diff --git a/doc/backup-upload.md b/doc/backup-upload.md index 212b16cb..08d64b04 100644 --- a/doc/backup-upload.md +++ b/doc/backup-upload.md @@ -3,8 +3,8 @@ Upload backup to server [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -12,6 +12,11 @@ Description This script uploads binary backup (`/ system backup save`) and complete configuration export (`/ export terse`) to external server. +> ⚠️ **Warning**: The used command can hit errors that a script can not handle. +> This may result in script termination (where no notification is sent) or +> malfunction of fetch command (where all up- and downloads break) for some +> time. Failed notifications are queued then. + ### Sample notification ![backup-upload notification](backup-upload.d/notification.svg) @@ -36,7 +41,9 @@ The configuration goes to `global-config-overlay`, these are the parameters: * `BackupUploadUser`: username for server authentication * `BackupUploadPass`: password for server authentication -Also notification settings are required for e-mail, matrix and/or telegram. +Also notification settings are required for e-mail, +[matrix](mod/notification-matrix.md) and/or +[telegram](mod/notification-telegram.md). ### Issues with SFTP client @@ -62,8 +69,9 @@ Creating a scheduler may be an option: See also -------- -* [Send backup via e-mail](backup-email.md) * [Upload backup to Mikrotik cloud](backup-cloud.md) +* [Send backup via e-mail](backup-email.md) +* [Save configuration to fallback partition](doc/backup-partition.md) --- [◀ Go back to main README](../README.md) diff --git a/doc/capsman-download-packages.md b/doc/capsman-download-packages.md index cdbd72b3..bac8a3cb 100644 --- a/doc/capsman-download-packages.md +++ b/doc/capsman-download-packages.md @@ -3,8 +3,8 @@ Download packages for CAP upgrade from CAPsMAN [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -26,18 +26,9 @@ Optionally add a scheduler to run after startup: / system scheduler add name=capsman-download-packages on-event="/ system script run capsman-download-packages;" start-time=startup; -Only packages available in older version are downloaded. For initial setup -place the required packages to CAPsMAN package path (see -`/ caps-man manager`). The packages can be downloaded from device with -function `$DownloadPackage`, use something like this to download latest -packages to directory `routeros`: - - $DownloadPackage system "" arm routeros; - $DownloadPackage security "" arm routeros; - [...] - $DownloadPackage system "" mipsbe routeros; - $DownloadPackage security "" mipsbe routeros; - [...] +Packages available in local storage in older version are downloaded +unconditionally. The script tries to download missing packages by guessing +from system log. Usage and invocation -------------------- diff --git a/doc/capsman-rolling-upgrade.md b/doc/capsman-rolling-upgrade.md index 92eafa69..34e3c91b 100644 --- a/doc/capsman-rolling-upgrade.md +++ b/doc/capsman-rolling-upgrade.md @@ -3,8 +3,8 @@ Run rolling CAP upgrades from CAPsMAN [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/certificate-renew-issued.md b/doc/certificate-renew-issued.md index 63d64085..d7c46768 100644 --- a/doc/certificate-renew-issued.md +++ b/doc/certificate-renew-issued.md @@ -3,8 +3,8 @@ Renew locally issued certificates [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/check-certificates.md b/doc/check-certificates.md index 44bee7a3..a553e6ac 100644 --- a/doc/check-certificates.md +++ b/doc/check-certificates.md @@ -3,8 +3,8 @@ Renew certificates and notify on expiration [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -27,7 +27,8 @@ Configuration ------------- The expiry notifications just require notification settings for e-mail, -matrix and/or telegram. +[matrix](mod/notification-matrix.md) and/or +[telegram](mod/notification-telegram.md). For automatic download and renewal of certificates you need configuration in `global-config-overlay`, these are the parameters: diff --git a/doc/check-health.md b/doc/check-health.md index 8e271d6c..f6900cee 100644 --- a/doc/check-health.md +++ b/doc/check-health.md @@ -3,8 +3,8 @@ Notify about health state [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -56,7 +56,9 @@ The configuration goes to `global-config-overlay`, these are the parameters: * `CheckHealthVoltageLow`: value (in volt*10) giving a hard lower limit * `CheckHealthVoltagePercent`: percentage value to trigger voltage jumps -Also notification settings are required for e-mail, matrix and/or telegram. +Also notification settings are required for e-mail, +[matrix](mod/notification-matrix.md) and/or +[telegram](mod/notification-telegram.md). --- [◀ Go back to main README](../README.md) diff --git a/doc/check-lte-firmware-upgrade.md b/doc/check-lte-firmware-upgrade.md index ef68bcb5..704a86bd 100644 --- a/doc/check-lte-firmware-upgrade.md +++ b/doc/check-lte-firmware-upgrade.md @@ -3,8 +3,8 @@ Notify on LTE firmware upgrade [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -35,7 +35,9 @@ Just install the script: Configuration ------------- -Notification setting are required for e-mail, matrix and/or telegram. +Notification setting are required for e-mail, +[matrix](mod/notification-matrix.md) and/or +[telegram](mod/notification-telegram.md). See also -------- diff --git a/doc/check-routeros-update.md b/doc/check-routeros-update.md index 9385341d..0710b76b 100644 --- a/doc/check-routeros-update.md +++ b/doc/check-routeros-update.md @@ -3,8 +3,8 @@ Notify on RouterOS update [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -14,11 +14,20 @@ The primary use of this script is to notify about RouterOS updates. Run from a terminal you can start the update process or schedule it. Centrally managing update process of several devices is possibly by -specifying versions safe to be updated on a web server. +specifying versions safe to be updated on a web server. Versions seen +in neighbor discovery can be specified to be safe as well. Also installing patch updates (where just last digit is increased) automatically is supported. +> ⚠️ **Warning**: Installing updates is important from a security point +> of view. At the same time it can be source of serve breakage. So test +> versions in lab and read +> [changelog](https://mikrotik.com/download/changelogs/) and +> [forum](https://forum.mikrotik.com/viewforum.php?f=21) before deploying +> to your production environment! Automatic updates should be handled +> with care! + ### Sample notification ![check-routeros-update notification](check-routeros-update.d/notification.svg) @@ -47,6 +56,10 @@ safe versions from a web server. The configuration goes to * `SafeUpdateUrl`: url to check for safe update, the channel (`long-term`, `stable` or `testing`) is appended +Also notification settings are required for e-mail, +[matrix](mod/notification-matrix.md) and/or +[telegram](mod/notification-telegram.md). + Usage and invocation -------------------- @@ -61,6 +74,7 @@ Installing script [packages-update](packages-update.md) gives extra options. See also -------- +* [Automatically upgrade firmware and reboot](firmware-upgrade-reboot.md) * [Manage system update](packages-update.md) --- diff --git a/doc/collect-wireless-mac.md b/doc/collect-wireless-mac.md index 380c89f3..5425f768 100644 --- a/doc/collect-wireless-mac.md +++ b/doc/collect-wireless-mac.md @@ -3,8 +3,8 @@ Collect MAC addresses in wireless access list [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -40,7 +40,9 @@ On first run a disabled access list entry acting as marker (with comment "`--- collected above ---`") is added. Move this entry to define where new entries are to be added. -Also notification settings are required for e-mail, matrix and/or telegram. +Also notification settings are required for e-mail, +[matrix](mod/notification-matrix.md) and/or +[telegram](mod/notification-telegram.md). Usage and invocation -------------------- diff --git a/doc/daily-psk.md b/doc/daily-psk.md index 105737a8..d2046913 100644 --- a/doc/daily-psk.md +++ b/doc/daily-psk.md @@ -3,8 +3,8 @@ Use wireless network with daily psk [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -51,7 +51,9 @@ Then add an access list entry: / interface wireless access-list add comment="Daily PSK" interface=wl-daily private-pre-shared-key="ToBeChangedDaily"; -Also notification settings are required for e-mail, matrix and/or telegram. +Also notification settings are required for e-mail, +[matrix](mod/notification-matrix.md) and/or +[telegram](mod/notification-telegram.md). --- [◀ Go back to main README](../README.md) diff --git a/doc/dhcp-lease-comment.md b/doc/dhcp-lease-comment.md index 0b8ceb2a..8679bfae 100644 --- a/doc/dhcp-lease-comment.md +++ b/doc/dhcp-lease-comment.md @@ -3,8 +3,8 @@ Comment DHCP leases with info from access list [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/dhcp-to-dns.md b/doc/dhcp-to-dns.md index 60eb29d0..245b4574 100644 --- a/doc/dhcp-to-dns.md +++ b/doc/dhcp-to-dns.md @@ -3,8 +3,8 @@ Create DNS records for DHCP leases [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/early-errors.md b/doc/early-errors.md index a16da7df..b3c68009 100644 --- a/doc/early-errors.md +++ b/doc/early-errors.md @@ -1,11 +1,2 @@ -Send notification with early errors -=================================== - -[◀ Go back to main README](../README.md) - -This script has been replace. Please migrate to +This script has been replaced. Please migrate to [Forward log messages via notification](log-forward.md). - ---- -[◀ Go back to main README](../README.md) -[▲ Go back to top](#top) diff --git a/doc/firmware-upgrade-reboot.md b/doc/firmware-upgrade-reboot.md new file mode 100644 index 00000000..c913d8ef --- /dev/null +++ b/doc/firmware-upgrade-reboot.md @@ -0,0 +1,36 @@ +Automatically upgrade firmware and reboot +========================================= + +[◀ 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 +----------- + +RouterOS and firmware are upgraded separately, activating the latter +requires an extra reboot. This script handles upgrade and reboot. + +> ⚠️ **Warning**: This *should* be bullet proof, but I can not guarantee. In +> worst case it has potential to cause a boot loop, so handle with care! + +Requirements and installation +----------------------------- + +Just install the script and create a scheduler: + + $ScriptInstallUpdate firmware-upgrade-reboot; + / system scheduler add name=firmware-upgrade-reboot on-event="/ system script run firmware-upgrade-reboot;" start-time=startup; + +Enjoy firmware being up to date and in sync with RouterOS. + +See also +-------- + +* [Notify on RouterOS update](check-routeros-update.md) +* [Manage system update](packages-update.md) + +--- +[◀ Go back to main README](../README.md) +[▲ Go back to top](#top) diff --git a/doc/global-wait.md b/doc/global-wait.md index 2d9dad31..2a7fbfaf 100644 --- a/doc/global-wait.md +++ b/doc/global-wait.md @@ -3,8 +3,8 @@ Wait for global functions and modules [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/gps-track.md b/doc/gps-track.md index e4e553c9..3b9c94f3 100644 --- a/doc/gps-track.md +++ b/doc/gps-track.md @@ -3,8 +3,8 @@ Send GPS position to server [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/hotspot-to-wpa.md b/doc/hotspot-to-wpa.md index f3dccdba..8733a7c1 100644 --- a/doc/hotspot-to-wpa.md +++ b/doc/hotspot-to-wpa.md @@ -3,8 +3,8 @@ Use WPA2 network with hotspot credentials [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -56,6 +56,7 @@ Create hotspot login credentials: Additionally templates can be created to give more options for access list: +* `action`: set to `reject` to ignore logins on that hotspot * `private-passphrase`: do **not** use passphrase from hotspot's user credentials, but given one - or unset (use default passphrase) with special word `ignore` diff --git a/doc/ipsec-to-dns.md b/doc/ipsec-to-dns.md index 9a0f4865..349ae63d 100644 --- a/doc/ipsec-to-dns.md +++ b/doc/ipsec-to-dns.md @@ -3,8 +3,8 @@ Create DNS records for IPSec peers [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/ipv6-update.md b/doc/ipv6-update.md index 994ea23b..ae4eb6af 100644 --- a/doc/ipv6-update.md +++ b/doc/ipv6-update.md @@ -3,8 +3,8 @@ Update configuration on IPv6 prefix change [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/lease-script.md b/doc/lease-script.md index 3d8a29bc..16fc73e3 100644 --- a/doc/lease-script.md +++ b/doc/lease-script.md @@ -3,19 +3,25 @@ Run other scripts on DHCP lease [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **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. Currently -it does: +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: -* run [collect-wireless-mac](collect-wireless-mac.md) -* run [dhcp-lease-comment](dhcp-lease-comment.md) -* run [dhcp-to-dns](dhcp-to-dns.md) -* run [hotspot-to-wpa](hotspot-to-wpa.md) + # 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 ----------------------------- diff --git a/doc/log-forward.md b/doc/log-forward.md index e3603b5e..1f3eae54 100644 --- a/doc/log-forward.md +++ b/doc/log-forward.md @@ -3,8 +3,8 @@ Forward log messages via notification [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -46,7 +46,9 @@ The configuration goes to `global-config-overlay`, these are the parameters: * `LogForwardIncludeMessage`: define message text to be forwarded (even if filter matches) -Also notification settings are required for e-mail, matrix and/or telegram. +Also notification settings are required for e-mail, +[matrix](mod/notification-matrix.md) and/or +[telegram](mod/notification-telegram.md). --- [◀ Go back to main README](../README.md) diff --git a/doc/mod/bridge-port-to.md b/doc/mod/bridge-port-to.md index 5b2817be..02d1e8da 100644 --- a/doc/mod/bridge-port-to.md +++ b/doc/mod/bridge-port-to.md @@ -1,10 +1,10 @@ Manage ports in bridge ====================== -[◀ Go back to main README](../README.md) +[◀ Go back to main README](../../README.md) -🛈 This module can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️️ **Info**: This module can not be used on its own but requires the base +> installation. See [main README](../../README.md) for details. Description ----------- @@ -77,5 +77,5 @@ See also * [Manage VLANs on bridge ports](bridge-port-vlan.md) --- -[◀ Go back to main README](../README.md) +[◀ Go back to main README](../../README.md) [▲ Go back to top](#top) diff --git a/doc/mod/bridge-port-vlan.md b/doc/mod/bridge-port-vlan.md index 67dd04d6..290826ee 100644 --- a/doc/mod/bridge-port-vlan.md +++ b/doc/mod/bridge-port-vlan.md @@ -3,8 +3,8 @@ Manage VLANs on bridge ports [◀ Go back to main README](../../README.md) -🛈 This module can not be used on its own but requires the base installation. -See [main README](../../README.md) for details. +> ℹ️️ **Info**: This module can not be used on its own but requires the base +> installation. See [main README](../../README.md) for details. Description ----------- diff --git a/doc/mod/inspectvar.d/inspectvar.avif b/doc/mod/inspectvar.d/inspectvar.avif new file mode 100644 index 00000000..d4a745f2 Binary files /dev/null and b/doc/mod/inspectvar.d/inspectvar.avif differ diff --git a/doc/mod/inspectvar.md b/doc/mod/inspectvar.md new file mode 100644 index 00000000..d3fb3b2c --- /dev/null +++ b/doc/mod/inspectvar.md @@ -0,0 +1,33 @@ +Inspect variables +================= + +[◀ Go back to main README](../../README.md) + +> ℹ️️ **Info**: This module can not be used on its own but requires the base +> installation. See [main README](../../README.md) for details. + +Description +----------- + +RouterOS handles not just scalar variables, but also arrays - even nested. +This module adds a function to inspect variables. + +Requirements and installation +----------------------------- + +Just install the module: + + $ScriptInstallUpdate mod/inspectvar; + +Usage and invocation +-------------------- + +Call the function `$InspectVar` with a variable as parameter: + + $InspectVar $ModeButton + +![InspectVar](inspectvar.d/inspectvar.avif) + +--- +[◀ Go back to main README](../../README.md) +[▲ Go back to top](#top) diff --git a/doc/mod/ipcalc.d/ipcalc.avif b/doc/mod/ipcalc.d/ipcalc.avif new file mode 100644 index 00000000..022f325b Binary files /dev/null and b/doc/mod/ipcalc.d/ipcalc.avif differ diff --git a/doc/mod/ipcalc.d/ipcalcreturn.avif b/doc/mod/ipcalc.d/ipcalcreturn.avif new file mode 100644 index 00000000..d858bb12 Binary files /dev/null and b/doc/mod/ipcalc.d/ipcalcreturn.avif differ diff --git a/doc/mod/ipcalc.md b/doc/mod/ipcalc.md new file mode 100644 index 00000000..a3e7fc8b --- /dev/null +++ b/doc/mod/ipcalc.md @@ -0,0 +1,53 @@ +IP address calculation +====================== + +[◀ Go back to main README](../../README.md) + +> ℹ️️ **Info**: This module can not be used on its own but requires the base +> installation. See [main README](../../README.md) for details. + +Description +----------- + +This module adds functions for IP address calculation. + +Requirements and installation +----------------------------- + +Just install the module: + + $ScriptInstallUpdate mod/ipcalc; + +Usage and invocation +-------------------- + +### IPCalc + +The function `$IPCalc` prints information to terminal, including: + +* address +* netmask +* network in CIDR notation +* minimum host address +* maximum host address +* broadcast address + +It expects an IP address in CIDR notation as argument. + + $IPCalc 192.168.88.1/24; + +![IPCalc](ipcalc.d/ipcalc.avif) + +### IPCalcReturn + +The function `$IPCalcReturn` expects an IP address in CIDR notation as +argument as well. But it does not print to terminal, instead it returns +the information in a named array. + + :put ([ $IPCalcReturn 192.168.88.1/24 ]->"broadcast"); + +![IPCalcReturn](ipcalc.d/ipcalcreturn.avif) + +--- +[◀ Go back to main README](../../README.md) +[▲ Go back to top](#top) diff --git a/doc/mod/notification-matrix.d/01-home-server.avif b/doc/mod/notification-matrix.d/01-home-server.avif new file mode 100644 index 00000000..8a79ae6a Binary files /dev/null and b/doc/mod/notification-matrix.d/01-home-server.avif differ diff --git a/doc/mod/notification-matrix.d/02-access-token.avif b/doc/mod/notification-matrix.d/02-access-token.avif new file mode 100644 index 00000000..8a0b6473 Binary files /dev/null and b/doc/mod/notification-matrix.d/02-access-token.avif differ diff --git a/doc/mod/notification-matrix.d/03-join-room.avif b/doc/mod/notification-matrix.d/03-join-room.avif new file mode 100644 index 00000000..c7fad4e8 Binary files /dev/null and b/doc/mod/notification-matrix.d/03-join-room.avif differ diff --git a/doc/mod/notification-matrix.md b/doc/mod/notification-matrix.md new file mode 100644 index 00000000..91a39e5a --- /dev/null +++ b/doc/mod/notification-matrix.md @@ -0,0 +1,100 @@ +Send notifications via Matrix +============================= + +[◀ Go back to main README](../../README.md) + +> ℹ️️ **Info**: This module can not be used on its own but requires the base +> installation. See [main README](../../README.md) for details. + +Description +----------- + +This module adds support for sending notifications via +[Matrix](https://matrix.org/) via client server api. A queue is used to +make sure notifications are not lost on failure but sent later. + +Requirements and installation +----------------------------- + +Just install the module: + + $ScriptInstallUpdate mod/notification-matrix; + +Also install a Matrix client on at least one of your mobile and/or desktop +devices. As there is no privilege separation you should create a dedicated +notification account, in addition to your general user account. + +Configuration +------------- + +Edit `global-config-overlay`, add `MatrixHomeServer`, `MatrixAccessToken` and +`MatrixRoom` - see below on hints how to retrieve this information. Then +reload the configuration. + +### Home server + +Matrix user accounts are identified by a unique user id in the form of +`@localpart:domain`. The `domain` part is not necessarily your home server +address, you have to resolve it with the procedure described in the +[Matrix specification](https://spec.matrix.org/latest/client-server-api/#server-discovery). + +Your best bet is to query the server at `domain` with the +[well-known uri](https://spec.matrix.org/latest/client-server-api/#well-known-uri). +For "*matrix.org*" this query is: + + / tool fetch "https://matrix.org/.well-known/matrix/client" output=user; + +![home server](notification-matrix.d/01-home-server.avif) + +So the home server for "*matrix.org*" is "*matrix-client.matrix.org*". +Please strip the protocol ("*https://*") for `MatrixHomeServer` if given. + +### Access token + +After discovering the correct home server an access token has to be created. +For this the login credentials (username and password) of the notification +account must be sent to the home server via +[client server api](https://matrix.org/docs/guides/client-server-api#login). + +We use the home server discovered above, "*matrix-client.matrix.org*". +The user is "*example*" and password is "*v3ry-s3cr3t*". + + / tool fetch "https://matrix-client.matrix.org/_matrix/client/r0/login" http-method=post http-data="{\"type\":\"m.login.password\", \"user\":\"example\", \"password\":\"v3ry-s3cr3t\"}" output=user; + +![access token](notification-matrix.d/02-access-token.avif) + +The server replied with a JSON object containing the `access_token`, use that +for `MatrixAccessToken`. + +### Room + +Every Matix chat is a room, so we have to create one. Do so with your general +user, this makes sure your general user is the room owner. Then join the room +and invite the notification user by its user id "*@example:matrix.org*". Look +up the room id within the Matrix client, it should read like +"*!WUcxpSjKyxSGelouhA:matrix.org*". Use that for `MatrixRoom`. + +Finally join the notification user to the room by accepting the invite. Again, +this can be done with +[client server api](https://matrix.org/docs/guides/client-server-api#joining-a-room-via-an-invite). +Make sure to replace room id ("*!*" is escaped with "*%21*") and access token +with your data. + + / tool fetch "https://matrix-client.matrix.org/_matrix/client/r0/rooms/%21WUcxpSjKyxSGelouhA:matrix.org/join?access_token=yt_ZXdvcm0tdGVzdA_NNqUyvKHRhBLZmnzVVSK_0xu6yN" http-method=post http-data="" output=user; + +![join room](notification-matrix.d/03-join-room.avif) + +Usage and invocation +-------------------- + +There's nothing special to do. Every script or function sending a notification +will now send it to your Matrix account. + +See also +-------- + +* [Send notifications via Telegram](notification-telegram.md) + +--- +[◀ Go back to main README](../../README.md) +[▲ Go back to top](#top) diff --git a/doc/mod/notification-telegram.d/newbot.avif b/doc/mod/notification-telegram.d/newbot.avif new file mode 100644 index 00000000..1fc7355f Binary files /dev/null and b/doc/mod/notification-telegram.d/newbot.avif differ diff --git a/doc/mod/notification-telegram.md b/doc/mod/notification-telegram.md new file mode 100644 index 00000000..435694e5 --- /dev/null +++ b/doc/mod/notification-telegram.md @@ -0,0 +1,63 @@ +Send notifications via Telegram +=============================== + +[◀ Go back to main README](../../README.md) + +> ℹ️️ **Info**: This module can not be used on its own but requires the base +> installation. See [main README](../../README.md) for details. + +Description +----------- + +This module adds support for sending notifications via +[Telegram](https://telegram.org/) via bot api. A queue is used to make sure +notifications are not lost on failure but sent later. + +Requirements and installation +----------------------------- + +Just install the module: + + $ScriptInstallUpdate mod/notification-telegram; + +Also install Telegram on at least one of your mobile and/or desktop devices +and create an account. + +Configuration +------------- + +Open Telegram, then start a chat with [BotFather](https://t.me/BotFather) and +create your own bot: + +![create new bot](notification-telegram.d/newbot.avif) + +Now open a chat with your bot and start it by clicking the `START` button. + +Open just another chat with [GetIDs Bot](https://t.me/getidsbot), again start +with the `START` button. It will send you some information, including the +`id`, just below `You`. + +Finally edit `global-config-overlay`, add `TelegramTokenId` with the token +from *BotFather* and `TelegramChatId` with your id from *GetIDs Bot*. Then +reload the configuration. + +### Notifications to a group + +Sending notifications to a group is possible as well. Add your bot and the +*GetIDs Bot* to a group, then use the group's id (which starts with a dash) +for `TelegramChatId`. Then remove *GetIDs Bot* from group. + +Usage and invocation +-------------------- + +There's nothing special to do. Every script or function sending a notification +will now send it to your Telegram account. + +See also +-------- + +* [Send notifications via Matrix](notification-matrix.md) + +--- +[◀ Go back to main README](../../README.md) +[▲ Go back to top](#top) diff --git a/doc/mod/scriptrunonce.d/hello-world.rsc b/doc/mod/scriptrunonce.d/hello-world.rsc new file mode 100644 index 00000000..17ec5752 --- /dev/null +++ b/doc/mod/scriptrunonce.d/hello-world.rsc @@ -0,0 +1,3 @@ +#!rsc by RouterOS + +:put ("Hello World from " . [ / system identity get name ] . "!"); diff --git a/doc/mod/scriptrunonce.d/scriptrunonce.avif b/doc/mod/scriptrunonce.d/scriptrunonce.avif new file mode 100644 index 00000000..614c72c6 Binary files /dev/null and b/doc/mod/scriptrunonce.d/scriptrunonce.avif differ diff --git a/doc/mod/scriptrunonce.md b/doc/mod/scriptrunonce.md new file mode 100644 index 00000000..aaa64a99 --- /dev/null +++ b/doc/mod/scriptrunonce.md @@ -0,0 +1,48 @@ +Download script and run it once +=============================== + +[◀ Go back to main README](../../README.md) + +> ℹ️️ **Info**: This module can not be used on its own but requires the base +> installation. See [main README](../../README.md) for details. + +Description +----------- + +This module adds a function that downloads a script, checks for syntax +validity and runs it once. + +Requirements and installation +----------------------------- + +Just install the module: + + $ScriptInstallUpdate mod/scriptrunonce; + +Configuration +------------- + +The optional configuration goes to `global-config-overlay`. + +* `ScriptRunOnceBaseUrl`: base url, prepended to parameter +* `ScriptRunOnceUrlSuffix`: url suffix, appended to parameter + +If the parameter passed to the function is not a complete URL (starting +with protocol `ftp://`, `http://`, `https://` or `sftp://`) the values are +prepended and appended. + +Usage and invocation +-------------------- + +The function `$ScriptRunOnce` expects an URL (or name if +`ScriptRunOnceBaseUrl` is given) pointing to a script as parameter. + + $ScriptRunOnce https://git.eworm.de/cgit/routeros-scripts/plain/doc/mod/scriptrunonce.d/hello-world.rsc + +![ScriptRunOnce](scriptrunonce.d/scriptrunonce.avif) + +Giving multiple scripts is possible, separated by comma. + +--- +[◀ Go back to main README](../../README.md) +[▲ Go back to top](#top) diff --git a/doc/mode-button.md b/doc/mode-button.md index 3cea7203..c1c059ef 100644 --- a/doc/mode-button.md +++ b/doc/mode-button.md @@ -3,8 +3,8 @@ Mode button with multiple presses [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/netwatch-dns.md b/doc/netwatch-dns.md index 96710a2c..4fbfc2be 100644 --- a/doc/netwatch-dns.md +++ b/doc/netwatch-dns.md @@ -3,8 +3,8 @@ Manage DNS and DoH servers from netwatch [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/netwatch-notify.md b/doc/netwatch-notify.md index 78a0eedf..b2f6dd02 100644 --- a/doc/netwatch-notify.md +++ b/doc/netwatch-notify.md @@ -3,8 +3,8 @@ Notify on host up and down [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -38,6 +38,8 @@ The hosts to be checked have to be added to netwatch with specific comment: / tool netwatch add comment="notify, hostname=example.com" host=[ :resolve "example.com" ]; +### Hooks + It is possible to run an up hook command (`up-hook`) or down hook command (`down-hook`) when a notification is triggered. This has to be added in comment, note that some characters need extra escaping: @@ -48,10 +50,14 @@ Also there is a `pre-down-hook` that fires at two thirds of failed checks required for the notification. The idea is to fix the issue before a notification is sent. +### Count threshould + The count threshould (default is 5 checks) is configurable as well: / tool netwatch add comment="notify, hostname=example.com, count=10" host=104.18.144.11; +### Parents & dependencies + If the host is behind another checked host add a dependency, this will suppress notification if the parent host is down: @@ -61,6 +67,8 @@ suppress notification if the parent host is down: Note that every configured parent in a chain increases the check count threshould by one. +### Update from DNS + The host address can be updated dynamically. Give extra parameter `resolve` with a resolvable name: @@ -70,7 +78,19 @@ But be warned: Dynamic updates will probably cause issues if the name has more than one record in dns - a high rate of configuration changes (and flash writes) at least. -Also notification settings are required for e-mail, matrix and/or telegram. +### No notification on host down + +Also suppressing the notification on host down is possible with parameter +`no-down-notification`. This may be desired for devices that are usually +powered off, but accessibility is of interest. + + / tool netwatch add comment="notify, hostname=printer, no-down-notification" host=10.0.0.30; + +Go and get your coffee ☕️ before sending the print job. + +Also notification settings are required for e-mail, +[matrix](mod/notification-matrix.md) and/or +[telegram](mod/notification-telegram.md). Tips & Tricks ------------- diff --git a/doc/ospf-to-leds.md b/doc/ospf-to-leds.md index 908fb565..2fba33e4 100644 --- a/doc/ospf-to-leds.md +++ b/doc/ospf-to-leds.md @@ -3,8 +3,8 @@ Visualize OSPF state via LEDs [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/packages-update.md b/doc/packages-update.md index ac693016..243e72be 100644 --- a/doc/packages-update.md +++ b/doc/packages-update.md @@ -3,8 +3,8 @@ Manage system update [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -41,8 +41,11 @@ See also -------- * [Notify on RouterOS update](check-routeros-update.md) +* [Upload backup to Mikrotik cloud](backup-cloud.md) * [Send backup via e-mail](backup-email.md) +* [Save configuration to fallback partition](doc/backup-partition.md) * [Upload backup to server](backup-upload.md) +* [Automatically upgrade firmware and reboot](firmware-upgrade-reboot.md) --- [◀ Go back to main README](../README.md) diff --git a/doc/ppp-on-up.md b/doc/ppp-on-up.md index 7514f822..ae58da5b 100644 --- a/doc/ppp-on-up.md +++ b/doc/ppp-on-up.md @@ -3,8 +3,8 @@ Run scripts on ppp connection [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/rotate-ntp.md b/doc/rotate-ntp.md index c151db24..775b977b 100644 --- a/doc/rotate-ntp.md +++ b/doc/rotate-ntp.md @@ -3,8 +3,8 @@ Rotate NTP servers [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/sms-action.md b/doc/sms-action.md index e36d384d..84427746 100644 --- a/doc/sms-action.md +++ b/doc/sms-action.md @@ -3,8 +3,8 @@ Act on received SMS [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/sms-forward.md b/doc/sms-forward.md index 873ccac9..9ebae694 100644 --- a/doc/sms-forward.md +++ b/doc/sms-forward.md @@ -3,8 +3,8 @@ Forward received SMS [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- @@ -31,8 +31,10 @@ Just install the script: Configuration ------------- -Notification settings are required for e-mail, matrix and/or telegram. Also -you have to enable receiving of SMS: +Notification settings are required for e-mail, +[matrix](mod/notification-matrix.md) and/or +[telegram](mod/notification-telegram.md). Also you have to enable receiving +of SMS: / tool sms set receive-enabled=yes; diff --git a/doc/update-gre-address.md b/doc/update-gre-address.md index e45e17a5..c19e138b 100644 --- a/doc/update-gre-address.md +++ b/doc/update-gre-address.md @@ -3,8 +3,8 @@ Update GRE configuration with dynamic addresses [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/doc/update-tunnelbroker.md b/doc/update-tunnelbroker.md index caff9ff6..9dd7f196 100644 --- a/doc/update-tunnelbroker.md +++ b/doc/update-tunnelbroker.md @@ -3,8 +3,8 @@ Update tunnelbroker configuration [◀ Go back to main README](../README.md) -🛈 This script can not be used on its own but requires the base installation. -See [main README](../README.md) for details. +> ℹ️ **Info**: This script can not be used on its own but requires the base +> installation. See [main README](../README.md) for details. Description ----------- diff --git a/email-backup b/email-backup deleted file mode 100644 index 2c48f071..00000000 --- a/email-backup +++ /dev/null @@ -1,2 +0,0 @@ -#!rsc by RouterOS -# dummy for migration diff --git a/firmware-upgrade-reboot b/firmware-upgrade-reboot new file mode 100644 index 00000000..ac2cb555 --- /dev/null +++ b/firmware-upgrade-reboot @@ -0,0 +1,41 @@ +#!rsc by RouterOS +# RouterOS script: firmware-upgrade-reboot +# Copyright (c) 2022 Christian Hesse +# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md +# +# install firmware upgrade, and reboot +# https://git.eworm.de/cgit/routeros-scripts/about/doc/firmware-upgrade-reboot.md + +:local 0 "firmware-upgrade-reboot"; +:global GlobalFunctionsReady; +:while ($GlobalFunctionsReady != true) do={ :delay 500ms; } + +:global LogPrintExit2; +:global VersionToNum; + +:local RouterBoard [ / system routerboard get ]; +:if ($RouterBoard->"current-firmware" = $RouterBoard->"upgrade-firmware") do={ + $LogPrintExit2 info $0 ("Firmware is already up to date.") true; +} +:if ([ $VersionToNum ($RouterBoard->"current-firmware") ] > [ $VersionToNum ($RouterBoard->"upgrade-firmware") ]) do={ + $LogPrintExit2 info $0 ("Different firmware version is available, but it is a downgrade. Ignoring.") true; +} + +:if ([ / system routerboard settings get auto-upgrade ] = false) do={ + $LogPrintExit2 info $0 ("Firmware version " . $RouterBoard->"upgrade-firmware" . \ + " is available, upgrading.") false; + / system routerboard upgrade; +} + +:while ([ :len [ / log find where topics=({"system";"info";"critical"}) \ + message="Firmware upgraded successfully, please reboot for changes to take effect!" ] ] = 0) do={ + :delay 1s; +} + +:local Uptime [ / system resource get uptime ]; +:if ($Uptime < 1m) do={ + :delay $Uptime; +} + +$LogPrintExit2 info $0 ("Firmware upgrade successful, rebooting.") false; +/ system reboot; diff --git a/global-config b/global-config index 024e52f5..d428da5d 100644 --- a/global-config +++ b/global-config @@ -8,7 +8,7 @@ # Make sure all configuration properties are up to date and this # value is in sync with value in script 'global-functions'! -:global GlobalConfigVersion 74; +:global GlobalConfigVersion 80; # This is used for DNS and backup file. :global Domain "example.com"; @@ -159,14 +159,11 @@ # alternative urls - main: stable code - next: currently in development #:global ScriptUpdatesBaseUrl "https://raw.githubusercontent.com/eworm-de/routeros-scripts/main/"; #:global ScriptUpdatesBaseUrl "https://raw.githubusercontent.com/eworm-de/routeros-scripts/next/"; -#:global ScriptUpdatesBaseUrl "https://raw.githubusercontent.com/eworm-de/routeros-scripts/routeros-v7/"; #:global ScriptUpdatesBaseUrl "https://gitlab.com/eworm-de/routeros-scripts/raw/main/"; #:global ScriptUpdatesBaseUrl "https://gitlab.com/eworm-de/routeros-scripts/raw/next/"; -#:global ScriptUpdatesBaseUrl "https://gitlab.com/eworm-de/routeros-scripts/raw/routeros-v7/"; :global ScriptUpdatesUrlSuffix ""; -# use next or routeros-v7 branch with default url (git.eworm.de) +# use next branch with default url (git.eworm.de) #:global ScriptUpdatesUrlSuffix "\?h=next"; -#:global ScriptUpdatesUrlSuffix "\?h=routeros-v7"; # Use this for defaults with $ScriptRunOnce # Install module with: diff --git a/global-config-overlay b/global-config-overlay index 37f78cfb..b5be6580 100644 --- a/global-config-overlay +++ b/global-config-overlay @@ -8,7 +8,10 @@ # Make sure all configuration properties are up to date and this # value is in sync with value in script 'global-functions'! # Comment or remove to disable news and change notifications. -:global GlobalConfigVersion 74; +:global GlobalConfigVersion 79; + +# Use branch routeros-v6 with RouterOS v6: +:global ScriptUpdatesUrlSuffix "\?h=routeros-v6"; # Copy configuration from global-config here and modify it. diff --git a/global-config.changes b/global-config.changes index a070ecd2..19630e99 100644 --- a/global-config.changes +++ b/global-config.changes @@ -73,11 +73,17 @@ 67="Moved modules to directory with shorter name."; 68="Reintroduced 'global-wait' for functions in scheduler."; 69="Support hard lower limit for voltage in 'check-health'."; - 70="MikroTik started pushing RouterOS v7. Changes are required if you run it, see https://git.eworm.de/cgit/routeros-scripts/about/#changes-for-routeros-v7"; - 71="MikroTik is pushing RouterOS v7 even more, in parallel branches. If you want to keep RouterOS v6 for some time see https://git.eworm.de/cgit/routeros-scripts/about/#changes-for-routeros-v6"; + 70="MikroTik started pushing RouterOS v7. Changes are required if you run it, see https://git.eworm.de/cgit/routeros-scripts/about/#requirements"; + 71="MikroTik is pushing RouterOS v7 even more, in parallel branches. If you want to keep RouterOS v6 for some time see https://git.eworm.de/cgit/routeros-scripts/about/#requirements"; 72="Introduced new script 'netwatch-dns' to manage DNS and DoH servers from netwatch."; 73="Renamed backup scripts ('cloud-backup' -> 'backup-cloud', 'email-backup' -> 'backup-email', 'upload-backup' -> 'backup-upload')."; 74="Extended 'hotspot-to-wpa', it can now read additional configuration from templates and hotspot users."; + 75="You are using the branch 'routeros-v6', well done."; + 76="Added an option to suppress notifications on host down with 'netwatch-notify'."; + 77="Introduced new script 'firmware-upgrade-reboot'. Handle with care!"; + 78="New documentation is online for notifications via Telegram & Matrix, variable inspection, ip address calculation and running scripts once."; + 79="Introduced new script 'backup-partition' to save configuration to fallback partition."; + 80="The 'routeros-v6' branch entered soft freeze state and will receive important updates only. Happy to welcome you in 'main' branch once moving to RouterOS v7!"; }; # Migration steps to be applied on script updates diff --git a/global-functions b/global-functions index 625bbe4f..e40e3843 100644 --- a/global-functions +++ b/global-functions @@ -7,8 +7,10 @@ # global functions # https://git.eworm.de/cgit/routeros-scripts/about/ +:local 0 "global-functions"; + # expected configuration version -:global ExpectedConfigVersion 74; +:global ExpectedConfigVersion 80; # global variables not to be changed by user :global GlobalFunctionsReady false; @@ -38,6 +40,7 @@ :global ParseKeyValueStore; :global QuotedPrintable; :global RandomDelay; +:global Read; :global RequiredRouterOS; :global ScriptFromTerminal; :global ScriptInstallUpdate; @@ -221,7 +224,8 @@ [ $IfThenElse ([ :typeof ($Update->"latest-version") ] != "nothing" && \ $Update->"installed-version" != $Update->"latest-version") \ ("\n Available: " . $Update->"latest-version") ] . \ - [ $IfThenElse ($RouterBoard->"routerboard" = true) \ + [ $IfThenElse ($RouterBoard->"routerboard" = true && \ + $RouterBoard->"current-firmware" != $RouterBoard->"upgrade-firmware") \ ("\n Firmware: " . $RouterBoard->"current-firmware") ] . \ "\nRouterOS-Scripts:" . \ "\n Current: " . $GlobalConfigVersion . \ @@ -252,6 +256,7 @@ :global CleanFilePath; :global LogPrintExit2; :global MkDir; + :global VersionToNum; :global WaitForFile; :if ([ :len $PkgName ] = 0) do={ :return false; } @@ -259,6 +264,9 @@ :if ([ :len $PkgArch ] = 0) do={ :set PkgArch [ / system resource get architecture-name ]; } :local PkgFile ($PkgName . "-" . $PkgVer . "-" . $PkgArch . ".npk"); + :if ([ $VersionToNum $PkgVer ] < [ $VersionToNum "7.0" ] && $PkgName = "routeros") do={ + :set PkgFile ($PkgName . "-" . $PkgArch . "-" . $PkgVer . ".npk"); + } :if ($PkgArch = "x86_64" || $PkgName ~ "^routeros-") do={ :set PkgFile ($PkgName . "-" . $PkgVer . ".npk"); } @@ -278,13 +286,13 @@ $LogPrintExit2 error $0 ("Downloading required certificate failed.") true; } + :local Url ("https://upgrade.mikrotik.com/routeros/" . $PkgVer . "/" . $PkgFile); $LogPrintExit2 info $0 ("Downloading package file '" . $PkgName . "'...") false; + $LogPrintExit2 debug $0 ("... from url: " . $Url) false; :local Retry 3; :while ($Retry > 0) do={ :do { - / tool fetch check-certificate=yes-without-crl \ - ("https://upgrade.mikrotik.com/routeros/" . $PkgVer . "/" . $PkgFile) \ - dst-path=$PkgDest; + / tool fetch check-certificate=yes-without-crl $Url dst-path=$PkgDest; $WaitForFile $PkgDest; :if ([ / file get [ find where name=$PkgDest ] type ] = "package") do={ @@ -353,6 +361,7 @@ :foreach Id,Message in=$EmailQueue do={ :if ([ :typeof $Message ] = "array" ) do={ :local Attach [ $EitherOr ($Message->"attach") "" ]; + :while ([ / tool e-mail get last-status ] = "in-progress") do={ :delay 1s; } / tool e-mail send to=($Message->"to") cc=($Message->"cc") subject=($Message->"subject") \ body=($Message->"body") file=$Attach; :local Wait true; @@ -476,7 +485,7 @@ :return ("\1B[" . $Color->$1 . "m" . $1 . "\1B[0m"); } - :local Log ($Name . ": " . $Message); + :local Log ([ $EitherOr $Name "" ] . ": " . $Message); :if ($Severity ~ ("^(debug|error|info)\$")) do={ :if ($Severity = "debug") do={ :log debug $Log; } :if ($Severity = "error") do={ :log error $Log; } @@ -506,6 +515,10 @@ :set Dir [ $CleanFilePath $Dir ]; + :if ($Dir = "") do={ + :return true; + } + :if ([ :len [ / file find where name=$Dir type="directory" ] ] = 1) do={ :return true; } @@ -630,6 +643,11 @@ :delay ([ $GetRandomNumber $1 ] . [ $EitherOr $2 "s" ]); } +# read input from user +:set Read do={ + :return; +} + # check for required RouterOS version :set RequiredRouterOS do={ :local Caller [ :tostr $1 ]; @@ -672,7 +690,8 @@ # install new scripts, update existing scripts :set ScriptInstallUpdate do={ - :local Scripts [ :toarray $1 ]; + :local Scripts [ :toarray $1 ]; + :local NewComment [ :tostr $2 ]; :global ExpectedConfigVersion; :global GlobalConfigVersion; @@ -699,7 +718,7 @@ :foreach Script in=$Scripts do={ :if ([ :len [ / system script find where name=$Script ] ] = 0) do={ $LogPrintExit2 info $0 ("Adding new script: " . $Script) false; - / system script add name=$Script source="#!rsc by RouterOS\n"; + / system script add name=$Script owner=$Script source="#!rsc by RouterOS\n" comment=$NewComment; } } @@ -719,28 +738,28 @@ :foreach Scheduler in=[ / system scheduler find where on-event~("\\b" . $ScriptVal->"name" . "\\b") ] do={ :local SchedulerVal [ / system scheduler get $Scheduler ]; :if ($ScriptVal->"policy" != $SchedulerVal->"policy") do={ - $LogPrintExit2 warning $0 ("Policies differ for script " . $ScriptVal->"name" . \ - " and its scheduler " . $SchedulerVal->"name" . "!") false; + $LogPrintExit2 warning $0 ("Policies differ for script '" . $ScriptVal->"name" . \ + "' and its scheduler '" . $SchedulerVal->"name" . "'!") false; } } :if ([ :len $SourceNew ] = 0 && $ScriptUpdatesFetch = true) do={ :local Comment [ $ParseKeyValueStore ($ScriptVal->"comment") ]; :if (!($Comment->"ignore" = true)) do={ - $LogPrintExit2 debug $0 ("Fetching script from url: " . $ScriptVal->"name") false; :do { :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"); } + :local Url ($BaseUrl . $ScriptVal->"name" . $UrlSuffix); - :local Result [ / tool fetch check-certificate=yes-without-crl \ - ($BaseUrl . $ScriptVal->"name" . $UrlSuffix) output=user as-value ]; + $LogPrintExit2 debug $0 ("Fetching script '" . $ScriptVal->"name" . "' from url: " . $Url) false; + :local Result [ / tool fetch check-certificate=yes-without-crl $Url output=user as-value ]; :if ($Result->"status" = "finished") do={ :set SourceNew ($Result->"data"); } } on-error={ - $LogPrintExit2 warning $0 ("Failed fetching " . $ScriptVal->"name") false; + $LogPrintExit2 warning $0 ("Failed fetching script '" . $ScriptVal->"name" . "'!") false; } } } @@ -761,18 +780,18 @@ :set ReloadGlobalFunctions true; } } else={ - $LogPrintExit2 warning $0 ("Syntax validation for script " . $ScriptVal->"name" . \ - " failed! Ignoring!") false; + $LogPrintExit2 warning $0 ("Syntax validation for script '" . $ScriptVal->"name" . \ + "' failed! Ignoring!") false; } } else={ - $LogPrintExit2 warning $0 ("Looks like new script " . $ScriptVal->"name" . \ - " is not valid (missing shebang). Ignoring!") false; + $LogPrintExit2 warning $0 ("Looks like new script '" . $ScriptVal->"name" . \ + "' is not valid (missing shebang). Ignoring!") false; } } else={ - $LogPrintExit2 debug $0 ("Script " . $ScriptVal->"name" . " did not change.") false; + $LogPrintExit2 debug $0 ("Script '" . $ScriptVal->"name" . "' did not change.") false; } } else={ - $LogPrintExit2 debug $0 ("No update for script " . $ScriptVal->"name" . ".") false; + $LogPrintExit2 debug $0 ("No update for script '" . $ScriptVal->"name" . "'.") false; } } @@ -800,11 +819,10 @@ :global GlobalConfigMigration; :local ChangeLogCode; - $LogPrintExit2 debug $0 ("Fetching news, changes and migration.") false; :do { - :local Result [ / tool fetch check-certificate=yes-without-crl \ - ($ScriptUpdatesBaseUrl . "global-config.changes" . $ScriptUpdatesUrlSuffix) \ - output=user as-value ]; + :local Url ($ScriptUpdatesBaseUrl . "global-config.changes" . $ScriptUpdatesUrlSuffix); + $LogPrintExit2 debug $0 ("Fetching news, changes and migration: " . $Url) false; + :local Result [ / tool fetch check-certificate=yes-without-crl $Url output=user as-value ]; :if ($Result->"status" = "finished") do={ :set ChangeLogCode ($Result->"data"); } @@ -1253,16 +1271,24 @@ # load modules :foreach Script in=[ / system script find where name ~ "^mod/." ] do={ - / system script run $Script; + :local ScriptVal [ / system script get $Script ]; + :if ([ $ValidateSyntax ($ScriptVal->"source") ] = true) do={ + :do { + / system script run $Script; + } on-error={ + $LogPrintExit2 error $0 ("Module '" . $ScriptVal->"name" . "' failed to run.") false; + } + } else={ + $LogPrintExit2 error $0 ("Module '" . $ScriptVal->"name" . "' failed syntax validation, skipping.") false; + } } # check for required RouterOS version -$RequiredRouterOS "global-functions" "6.47" true; +$RequiredRouterOS $0 "6.47" true; # ... and give a hint on RouterOS v7. -:if ([ $RequiredRouterOS "global-functions" "7.0" false ] = true) do={ - $LogPrintExit2 warning $0 ("RouterOS v7 brings some incompatible changes. Please switch to branch " . \ - "'routeros-v7', see https://git.eworm.de/cgit/routeros-scripts/about/#changes-for-routeros-v7") false; +:if ([ $RequiredRouterOS $0 "7.0" false ] = true) do={ + $LogPrintExit2 warning $0 ("RouterOS v7 brings some incompatible changes. Please switch to main branch!") false; } # signal we are ready diff --git a/global-wait b/global-wait index 9f3d438a..43cc5cc6 100644 --- a/global-wait +++ b/global-wait @@ -3,8 +3,6 @@ # Copyright (c) 2020-2022 Christian Hesse # https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md # -# provides: backup-script -# # wait for global-functions to finish # https://git.eworm.de/cgit/routeros-scripts/about/doc/global-wait.md diff --git a/hotspot-to-wpa b/hotspot-to-wpa index c40e08a1..628d7486 100644 --- a/hotspot-to-wpa +++ b/hotspot-to-wpa @@ -17,8 +17,9 @@ :local MacAddress $"mac-address"; :local UserName $username; :local Date [ / system clock get date ]; -:local Hotspot [ / ip hotspot host get [ find where mac-address=$MacAddress authorized ] server ]; :local UserVal [ / ip hotspot user get [ find where name=$UserName ] ]; +:local UserInfo [ $ParseKeyValueStore ($UserVal->"comment") ]; +:local Hotspot [ / ip hotspot host get [ find where mac-address=$MacAddress authorized ] server ]; :if ([ :len [ / caps-man access-list find where comment="--- hotspot-to-wpa above ---" disabled ] ] = 0) do={ / caps-man access-list add comment="--- hotspot-to-wpa above ---" disabled=yes; @@ -26,18 +27,29 @@ } :local PlaceBefore ([ / caps-man access-list find where comment="--- hotspot-to-wpa above ---" disabled ]->0); +:if ([ :len [ / caps-man access-list find where \ + comment=("hotspot-to-wpa template " . $Hotspot) disabled ] ] = 0) do={ + / caps-man access-list add comment=("hotspot-to-wpa template " . $Hotspot) disabled=yes place-before=$PlaceBefore; + $LogPrintExit2 warning $0 ("Added template in access-list for hotspot '" . $Hotspot . "'.") false; +} +:local Template [ / caps-man access-list get ([ find where \ + comment=("hotspot-to-wpa template " . $Hotspot) disabled ]->0) ]; + +:if ($Template->"action" = "reject") do={ + $LogPrintExit2 info $0 ("Ignoring login for hotspot '" . $Hotspot . "'.") true; +} + +# allow login page to load +:delay 1s; + $LogPrintExit2 info $0 ("Adding/updating accesslist entry for mac address " . $MacAddress . \ " (user " . $UserName . ").") false; - / caps-man access-list remove [ find where mac-address=$MacAddress comment~"^hotspot-to-wpa: " ]; / caps-man access-list add comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) \ mac-address=$MacAddress private-passphrase=($UserVal->"password") ssid-regexp="-wpa\$" place-before=$PlaceBefore; -:local Template [ / caps-man access-list get ([ find where comment=("hotspot-to-wpa template " . $Hotspot) disabled ]->0) ]; -:local UserInfo [ $ParseKeyValueStore ($UserVal->"comment") ]; :local Entry [ / caps-man access-list find where mac-address=$MacAddress \ comment=("hotspot-to-wpa: " . $UserName . ", " . $MacAddress . ", " . $Date) ]; - :local PrivatePassphrase [ $EitherOr ($UserInfo->"private-passphrase") ($Template->"private-passphrase") ]; :if ([ :len $PrivatePassphrase ] > 0) do={ :if ($PrivatePassphrase = "ignore") do={ diff --git a/netwatch-dns b/netwatch-dns index e731d953..e2fcfa31 100644 --- a/netwatch-dns +++ b/netwatch-dns @@ -43,12 +43,14 @@ $ScriptLock $0; :if ($DnsServers != $DnsCurrent) do={ $LogPrintExit2 info $0 ("Updating DNS servers: " . [ :tostr $DnsServers ]) false; / ip dns set servers=$DnsServers; + / ip dns cache flush; } } else={ :if ([ :len $DnsFallback ] > 0) do={ :if ($DnsFallback != $DnsCurrent) do={ $LogPrintExit2 info $0 ("Updating DNS servers to fallback: " . [ :tostr $DnsFallback ]) false; / ip dns set servers=$DnsFallback; + / ip dns cache flush; } } } @@ -69,10 +71,12 @@ $ScriptLock $0; :if ($DohServer != $DohCurrent) do={ $LogPrintExit2 info $0 ("Updating DoH server: " . $DohServer) false; / ip dns set use-doh-server=$DohServer; + / ip dns cache flush; } } else={ :if ($DohCurrent != "") do={ $LogPrintExit2 info $0 ("DoH server (" . $DohCurrent . ") is down, disabling.") false; / ip dns set use-doh-server=""; + / ip dns cache flush; } } diff --git a/netwatch-notify b/netwatch-notify index ae89cfb2..34a9e8fe 100644 --- a/netwatch-notify +++ b/netwatch-notify @@ -66,21 +66,23 @@ $ScriptLock $0; :set $Metric ($NetwatchNotify->$HostName); } - :if ([ :typeof ($HostInfo->"resolve") ] = "str" && [ $DNSIsResolving ] = true) do={ - :do { - :local Resolve [ :resolve ($HostInfo->"resolve") ]; - :if ($Resolve != $HostVal->"host") do={ - $LogPrintExit2 info $0 ("Name '" . $HostInfo->"resolve" . [ $IfThenElse ($HostInfo->"resolve" != \ - $HostInfo->"hostname") ("' for host '" . $HostInfo->"hostname") "" ] . \ - "' resolves to different address " . $Resolve . ", updating.") false; - / tool netwatch set host=$Resolve $Host; - :set ($Metric->"resolve-failed") false; - } - } on-error={ - :if ($Metric->"resolve-failed" != true) do={ - $LogPrintExit2 warning $0 ("Resolving name '" . $HostInfo->"resolve" . [ $IfThenElse ($HostInfo->"resolve" != \ - $HostInfo->"hostname") ("' for host '" . $HostInfo->"hostname") "" ] . "' failed.") false; - :set ($Metric->"resolve-failed") true; + :if ([ :typeof ($HostInfo->"resolve") ] = "str") do={ + :if ([ $DNSIsResolving ] = true) do={ + :do { + :local Resolve [ :resolve ($HostInfo->"resolve") ]; + :if ($Resolve != $HostVal->"host") do={ + $LogPrintExit2 info $0 ("Name '" . $HostInfo->"resolve" . [ $IfThenElse ($HostInfo->"resolve" != \ + $HostInfo->"hostname") ("' for host '" . $HostInfo->"hostname") "" ] . \ + "' resolves to different address " . $Resolve . ", updating.") false; + / tool netwatch set host=$Resolve $Host; + :set ($Metric->"resolve-failed") false; + } + } on-error={ + :if ($Metric->"resolve-failed" != true) do={ + $LogPrintExit2 warning $0 ("Resolving name '" . $HostInfo->"resolve" . [ $IfThenElse ($HostInfo->"resolve" != \ + $HostInfo->"hostname") ("' for host '" . $HostInfo->"hostname") "" ] . "' failed.") false; + :set ($Metric->"resolve-failed") true; + } } } } @@ -122,10 +124,10 @@ $ScriptLock $0; :set Parent ($NetwatchNotify->$Parent->"parent"); } } - $LogPrintExit2 info $0 ("Host " . $HostName . " (" . $HostVal->"host" . ") is down for " . \ - $Metric->"count" . " checks, " . [ $IfThenElse ($ParentNotified = false) [ $IfThenElse \ - ($Metric->"notified" = true) ("already notified.") ($Count - $Metric->"count" . " to go.") ] \ - ("parent host " . $Parent . " is down.") ]) false; + $LogPrintExit2 [ $IfThenElse ($HostInfo->"no-down-notification" != true) info debug ] $0 \ + ("Host " . $HostName . " (" . $HostVal->"host" . ") is down for " . $Metric->"count" . " checks, " . \ + [ $IfThenElse ($ParentNotified = false) [ $IfThenElse ($Metric->"notified" = true) ("already notified.") \ + ($Count - $Metric->"count" . " to go.") ] ("parent host " . $Parent . " is down.") ]) false; :if ((($Count * 2) - ($Metric->"count" * 3)) / 2 = 0 && [ :typeof ($HostInfo->"pre-down-hook") ] = "str") do={ $NetwatchNotifyHook $HostName "pre-down" ($HostInfo->"pre-down-hook"); } @@ -134,9 +136,11 @@ $ScriptLock $0; :if ([ :typeof ($HostInfo->"down-hook") ] = "str") do={ :set Message ($Message . "\n\n" . [ $NetwatchNotifyHook $HostName "down" ($HostInfo->"down-hook") ]); } - $SendNotification2 ({ origin=$0; \ - subject=([ $SymbolForNotification "cross-mark" ] . "Netwatch Notify: " . $HostName . " down"); \ - message=$Message }); + :if ($HostInfo->"no-down-notification" != true) do={ + $SendNotification2 ({ origin=$0; \ + subject=([ $SymbolForNotification "cross-mark" ] . "Netwatch Notify: " . $HostName . " down"); \ + message=$Message }); + } :set ($Metric->"notified") true; } } diff --git a/packages-update b/packages-update index b6b05246..2e6d8be0 100644 --- a/packages-update +++ b/packages-update @@ -35,7 +35,7 @@ $ScriptLock $0; :if ($NumInstalled > $NumLatest) do={ :if ([ $ScriptFromTerminal $0 ] = true) do={ :put "Latest version is older than installed one. Want to downgrade? [y/N]"; - :if (([ :terminal inkey timeout=60 ] % 32) = 25) do={ + :if (([ / terminal inkey timeout=60 ] % 32) = 25) do={ :set DoDowngrade true; } else={ :put "Canceled..."; @@ -61,7 +61,7 @@ $ScriptLock $0; $LogPrintExit2 warning $0 ("Running backup script " . $ScriptName . " before update failed!") false; :if ([ $ScriptFromTerminal $0 ] = true) do={ :put "Do you want to continue anyway? [y/N]"; - :if (([ :terminal inkey timeout=60 ] % 32) = 25) do={ + :if (([ / terminal inkey timeout=60 ] % 32) = 25) do={ $LogPrintExit2 info $0 ("User requested to continue anyway.") false; } else={ $LogPrintExit2 info $0 ("Canceled update...") true; @@ -80,7 +80,7 @@ $ScriptLock $0; :if ([ $ScriptFromTerminal $0 ] = true) do={ :put "Do you want to (s)chedule reboot or (r)eboot now? [s/R]"; - :if (([ :terminal inkey timeout=60 ] % 32) = 19) do={ + :if (([ / terminal inkey timeout=60 ] % 32) = 19) do={ / system scheduler add name="reboot-for-update" start-time=03:00:00 interval=1d \ on-event=(":global RandomDelay; \$RandomDelay 3600; " . \ "/ system scheduler remove reboot-for-update; / system reboot;"); diff --git a/upload-backup b/upload-backup deleted file mode 100644 index 2c48f071..00000000 --- a/upload-backup +++ /dev/null @@ -1,2 +0,0 @@ -#!rsc by RouterOS -# dummy for migration