Compare commits

...

51 commits

Author SHA1 Message Date
Christian Hesse
67aea8d5e4 global-functions: $ScriptInstallUpdate: fix indention 2026-01-19 16:09:41 +01:00
Christian Hesse
83d6335379 global-functions: $ScriptInstallUpdate: use :continue in loop 2026-01-19 16:08:37 +01:00
Christian Hesse
8097ebb1fc fw-addr-lists: fix indention 2026-01-19 15:38:50 +01:00
Christian Hesse
58672a7fef fw-addr-lists: use :continue in loop 2026-01-19 15:38:00 +01:00
Christian Hesse
511f1cc0f5 doc/mod/ssh-keys-import: update for RouterOS 7.21 2026-01-19 15:31:45 +01:00
Christian Hesse
617a86a932 mod/ssh-keys-import: drop old property
The property name changed in RouterOS 7.21beta2, so bump required
version to 7.21.
2026-01-19 15:31:45 +01:00
Christian Hesse
6772085430 telegram-chat: use :continue in loop 2026-01-19 15:31:45 +01:00
Christian Hesse
104639264a global-functions: $ExitError: drop argument $ExitOK...
... as the is no longer required with early exit with :exit.
2026-01-19 15:31:45 +01:00
Christian Hesse
4dee3a9d62 update-tunnelbroker: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
9fe72867cb update-gre-address: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
a14d2da314 sms-forward: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
878087d855 sms-action: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
07671470f4 ppp-on-up: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
25abe5797c packages-update: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
d2e6adf529 ospf-to-leds: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
eeb449e882 netwatch-notify: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
8329bded23 log-forward: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
f77c0f4a37 lease-script: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
02d4adbe44 ipv6-update: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
c0f08d4799 ipsec-to-dns: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
9c628f5a7a hotspot-to-wpa-cleanup: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
b76cd6df02 hotspot-to-wpa: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
51077a8d0a gps-track: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
74f2e1af7c fw-addr-lists: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
e3bfd3be01 firmware-upgrade-reboot: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
c255b5bfa8 dhcp-to-dns: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
88a4082475 dhcp-lease-comment: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
709acb964c daily-psk: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
d7bbeb6a03 collect-wireless-mac: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
ae2251052f check-routeros-update: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
a1f2b00a8b check-perpetual-license: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
11e9631074 check-lte-firmware-upgrade: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
46cbbc0e15 check-health: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
860a439dc3 check-certificates: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
1a05b85bd7 certificate-renew-issued: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
b1cd1410cb capsman-rolling-upgrade: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
8b6379ad4e capsman-download-packages: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
49a7ce9f69 backup-upload: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
12cff010b9 backup-partition: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
d4da1512cf backup-email: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
9e8abb8e14 backup-cloud: early exit with :exit 2026-01-19 15:27:26 +01:00
Christian Hesse
f00174aab2 telegram-chat: early exit with :exit 2026-01-19 14:56:51 +01:00
Christian Hesse
f34feb2b1b netwatch-dns: early exit with :exit 2026-01-19 14:56:51 +01:00
Christian Hesse
54a9ebd270 global-functions: drop $HexToNum 2026-01-19 14:56:51 +01:00
Christian Hesse
75a0124e82 log-forward: fix indention 2026-01-19 14:56:51 +01:00
Christian Hesse
46702c4ff6 log-forward: use comparison for ids
This was introduced with RouterOS 7.22beta1.

Initializing $LogForwardLast with boolean value looks odd, but this is
reuqired to match the very first message.
2026-01-19 14:56:51 +01:00
Christian Hesse
4857b6ba8b check-certificates: drop the compatibility workaround...
... and make it depend in RouterOS 7.19 and its builtin certificates.
2026-01-19 14:56:51 +01:00
Christian Hesse
996b8e2c5d global-functions: $CertificateAvailable: drop the compatibility workaround...
... and make it depend in RouterOS 7.19 and its builtin certificates.
2026-01-19 14:56:51 +01:00
Christian Hesse
73f65c82bd INITIAL-COMMANDS: drop the compatibility workaround...
... and make it depend in RouterOS 7.19 and its builtin certificates.
2026-01-19 14:56:51 +01:00
Christian Hesse
f1333087d2 mode-button: drop unused variable $ExitOK 2026-01-19 14:55:19 +01:00
Christian Hesse
e6542ba8cc accesslist-duplicates: drop unused variable $ExitOK 2026-01-19 14:54:32 +01:00
74 changed files with 368 additions and 575 deletions

View file

@ -4,7 +4,7 @@ Initial commands
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.17-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.19-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
@ -26,7 +26,7 @@ Run the complete base installation:
:if (!((($CertSettings->"builtin-trust-anchors") = "trusted" || \
($CertSettings->"builtin-trust-store") ~ "fetch" || \
($CertSettings->"builtin-trust-store") = "all") && \
[[ :parse (":return [ :len [ /certificate/builtin/find where common-name=\"" . $CertCommonName . "\" ] ]") ]] > 0)) do={
[ :len [ /certificate/builtin/find where common-name=$CertCommonName ] ] > 0)) do={
:put "Importing certificate...";
/tool/fetch ($BaseUrl . "certs/" . $CertFileName) dst-path=$CertFileName as-value;
:delay 1s;

View file

@ -4,7 +4,7 @@ RouterOS Scripts
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.17-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.19-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)

View file

@ -10,7 +10,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -33,5 +32,5 @@
:set ($Seen->$Mac) 1;
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -10,7 +10,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -33,5 +32,5 @@
:set ($Seen->$Mac) 1;
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -42,5 +41,5 @@
:set ($Seen->$Mac) 1;
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -10,7 +10,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -33,5 +32,5 @@
:set ($Seen->$Mac) 1;
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -9,7 +9,6 @@
# upload backup to MikroTik cloud
# https://rsc.eworm.de/doc/backup-cloud.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -36,15 +35,13 @@
:if ([ $ScriptLock $ScriptName ] = false) do={
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
:if ([ :len [ /system/scheduler/find where name="running-from-backup-partition" ] ] > 0) do={
$LogPrint warning $ScriptName ("Running from backup partition, refusing to act.");
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -55,8 +52,7 @@
:if ([ $MkDir ("tmpfs/backup-cloud") ] = false) do={
$LogPrint error $ScriptName ("Failed creating directory!");
:set ExitOK true;
:error false;
:exit;
}
:local I 5;
@ -100,5 +96,5 @@
}
$RmDir "tmpfs/backup-cloud";
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -9,7 +9,6 @@
# create and email backup and config file
# https://rsc.eworm.de/doc/backup-email.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -41,28 +40,24 @@
:if ([ :typeof $SendEMail2 ] = "nothing") do={
$LogPrint error $ScriptName ("The module for sending notifications via e-mail is not installed.");
:set ExitOK true;
:error false;
:exit;
}
:if ($BackupSendBinary != true && \
$BackupSendExport != true) do={
$LogPrint error $ScriptName ("Configured to send neither backup nor config export.");
:set ExitOK true;
:error false;
:exit;
}
:if ([ $ScriptLock $ScriptName ] = false) do={
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
:if ([ :len [ /system/scheduler/find where name="running-from-backup-partition" ] ] > 0) do={
$LogPrint warning $ScriptName ("Running from backup partition, refusing to act.");
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -82,8 +77,7 @@
:if ([ $MkDir $DirName ] = false) do={
$LogPrint error $ScriptName ("Failed creating directory!");
:set ExitOK true;
:error false;
:exit;
}
# binary backup
@ -139,5 +133,5 @@
}
# do not remove the files here, as the mail is still queued!
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -10,7 +10,6 @@
# save configuration to fallback partition
# https://rsc.eworm.de/doc/backup-partition.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -45,22 +44,19 @@
:if ([ $ScriptLock $ScriptName ] = false) do={
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
:if ([ :len [ /system/scheduler/find where name="running-from-backup-partition" ] ] > 0) do={
$LogPrint warning $ScriptName ("Running from backup partition, refusing to act.");
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
:if ([ :len [ /partitions/find ] ] < 2) do={
$LogPrint error $ScriptName ("Device does not have a fallback partition.");
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
:local ActiveRunning [ /partitions/find where active running ];
@ -68,8 +64,7 @@
:if ([ :len $ActiveRunning ] < 1) do={
$LogPrint error $ScriptName ("Device is not running from active partition.");
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
:local FallbackToName [ /partitions/get $ActiveRunning fallback-to ];
@ -78,8 +73,7 @@
:if ([ :len $FallbackTo ] < 1) do={
$LogPrint error $ScriptName ("There is no inactive partition named '" . $FallbackToName . "'.");
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
:if ([ /partitions/get $ActiveRunning version ] != [ /partitions/get $FallbackTo version]) do={
@ -88,8 +82,7 @@
:if (([ /terminal/inkey timeout=60 ] % 32) = 25) do={
:if ([ $CopyTo $ScriptName $FallbackTo $FallbackToName ] = false) do={
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
}
} else={
@ -101,8 +94,7 @@
($NumInstalled & $BitMask) != ($NumLatest & $BitMask)) do={
:if ([ $CopyTo $ScriptName $FallbackTo $FallbackToName ] = false) do={
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
}
}
@ -120,9 +112,8 @@
$LogPrint error $ScriptName ("Failed saving configuration to partition '" . \
$FallbackToName . "': " . $Err);
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -10,7 +10,6 @@
# create and upload backup and config file
# https://rsc.eworm.de/doc/backup-upload.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -47,21 +46,18 @@
:if ($BackupSendBinary != true && \
$BackupSendExport != true) do={
$LogPrint error $ScriptName ("Configured to send neither backup nor config export.");
:set ExitOK true;
:error false;
:exit;
}
:if ([ $ScriptLock $ScriptName ] = false) do={
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
:if ([ :len [ /system/scheduler/find where name="running-from-backup-partition" ] ] > 0) do={
$LogPrint warning $ScriptName ("Running from backup partition, refusing to act.");
:set PackagesUpdateBackupFailure true;
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -81,8 +77,7 @@
:if ([ $MkDir $DirName ] = false) do={
$LogPrint error $ScriptName ("Failed creating directory!");
:set ExitOK true;
:error false;
:exit;
}
# binary backup
@ -174,5 +169,5 @@
}
$RmDir $DirName;
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -28,8 +27,7 @@
:global WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -39,16 +37,14 @@
:if ([ :len $PackagePath ] = 0) do={
$LogPrint warning $ScriptName ("The CAPsMAN package path is not defined, can not download packages.");
:set ExitOK true;
:error false;
:exit;
}
:if ([ $FileGet $PackagePath ] = false) do={
:if ([ $MkDir $PackagePath ] = false) do={
$LogPrint warning $ScriptName ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!");
:set ExitOK true;
:error false;
:exit;
}
$LogPrint info $ScriptName ("Created directory at CAPsMAN package path (" . $PackagePath . \
"). Please place your packages!");
@ -89,5 +85,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -12,7 +12,6 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -29,8 +28,7 @@
:global WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -41,16 +39,14 @@
:if ([ :len $PackagePath ] = 0) do={
$LogPrint warning $ScriptName ("The CAPsMAN package path is not defined, can not download packages.");
:set ExitOK true;
:error false;
:exit;
}
:if ([ $FileGet $PackagePath ] = false) do={
:if ([ $MkDir $PackagePath ] = false) do={
$LogPrint warning $ScriptName ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!");
:set ExitOK true;
:error false;
:exit;
}
$LogPrint info $ScriptName ("Created directory at CAPsMAN package path (" . $PackagePath . \
"). Please place your packages!");
@ -100,5 +96,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -28,8 +27,7 @@
:global WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -39,16 +37,14 @@
:if ([ :len $PackagePath ] = 0) do={
$LogPrint warning $ScriptName ("The CAPsMAN package path is not defined, can not download packages.");
:set ExitOK true;
:error false;
:exit;
}
:if ([ $FileGet $PackagePath ] = false) do={
:if ([ $MkDir $PackagePath ] = false) do={
$LogPrint warning $ScriptName ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!");
:set ExitOK true;
:error false;
:exit;
}
$LogPrint info $ScriptName ("Created directory at CAPsMAN package path (" . $PackagePath . \
"). Please place your packages!");
@ -91,5 +87,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -12,7 +12,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -23,8 +22,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:local InstalledVersion [ /system/package/update/get installed-version ];
@ -46,5 +44,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -13,7 +13,6 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -24,8 +23,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:local InstalledVersion [ /system/package/update/get installed-version ];
@ -54,5 +52,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -12,7 +12,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -23,8 +22,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:local InstalledVersion [ /system/package/update/get installed-version ];
@ -47,5 +45,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -8,7 +8,6 @@
# renew locally issued certificates
# https://rsc.eworm.de/doc/certificate-renew-issued.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -22,8 +21,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:foreach Cert in=[ /certificate/find where issued expires-after<3w ] do={
@ -48,5 +46,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -3,13 +3,12 @@
# Copyright (c) 2013-2026 Christian Hesse <mail@eworm.de>
# https://rsc.eworm.de/COPYING.md
#
# requires RouterOS, version=7.17
# requires RouterOS, version=7.19
# requires device-mode, fetch
#
# check for certificate validity
# https://rsc.eworm.de/doc/check-certificates.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -117,10 +116,7 @@
:local Return "";
:for I from=0 to=5 do={
:set Return ($Return . [ $ParseKeyValueStore ($CertVal->"issuer") ]->"CN");
:local CertSettings [ /certificate/settings/get ];
:if (([ :len ($CertSettings->"builtin-trust-anchors") ] > 0 || \
[ :len ($CertSettings->"builtin-trust-store") ] > 0) && \
[[ :parse (":return [ :len [ /certificate/builtin/find where skid=\"" . ($CertVal->"akid") . "\" ] ]") ]] > 0) do={
:if ([ :len [ /certificate/builtin/find where skid=($CertVal->"akid") ] ] > 0) do={
:return $Return;
}
:do {
@ -152,8 +148,7 @@
}
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -252,5 +247,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -8,7 +8,6 @@
# check for RouterOS health state
# https://rsc.eworm.de/doc/check-health.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -37,8 +36,7 @@
}
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:local Resource [ /system/resource/get ];
@ -77,8 +75,7 @@
:local Plugins [ /system/script/find where name~"^check-health\\.d/." ];
:if ([ :len $Plugins ] = 0) do={
$LogPrint debug $ScriptName ("No plugins installed.");
:set ExitOK true;
:error true;
:exit;
}
:global CheckHealthPlugins ({});
@ -106,5 +103,5 @@
:set CheckHealthPlugins;
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -8,7 +8,6 @@
# check for LTE firmware upgrade, send notification
# https://rsc.eworm.de/doc/check-lte-firmware-upgrade.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -20,8 +19,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :typeof $SentLteFirmwareUpgradeNotification ] != "array") do={
@ -103,5 +101,5 @@
$CheckInterface $ScriptName $Interface;
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -8,7 +8,6 @@
# check perpetual license on CHR
# https://rsc.eworm.de/doc/check-perpetual-license.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -25,8 +24,7 @@
:global WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -34,8 +32,7 @@
:local License [ /system/license/get ];
:if ([ :typeof ($License->"deadline-at") ] != "str") do={
$LogPrint info $ScriptName ("This device does not have a perpetual license.");
:set ExitOK true;
:error true;
:exit;
}
:if ([ :len ($License->"next-renewal-at") ] = 0 && ($License->"limited-upgrades") = true) do={
@ -47,8 +44,7 @@
", can no longer update RouterOS on " . $Identity . "...") });
:set SentCertificateNotification "expired";
}
:set ExitOK true;
:error true;
:exit;
}
:if ([ :totime ($License->"deadline-at") ] - 3w < [ :timestamp ]) do={
@ -60,8 +56,7 @@
($License->"deadline-at") . " on " . $Identity . "...") });
:set SentCertificateNotification "warning";
}
:set ExitOK true;
:error true;
:exit;
}
:if ([ :typeof $SentCertificateNotification ] = "str" && \
@ -74,5 +69,5 @@
:set SentCertificateNotification;
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -9,7 +9,6 @@
# check for RouterOS update, send notification and/or install
# https://rsc.eworm.de/doc/check-routeros-update.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -47,14 +46,12 @@
}
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :len [ /system/scheduler/find where name="running-from-backup-partition" ] ] > 0) do={
$LogPrint warning $ScriptName ("Running from backup partition, refusing to act.");
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -65,8 +62,7 @@
/system/scheduler/remove "_RebootForUpdate";
} else={
$LogPrint info $ScriptName ("A reboot for update is already scheduled.");
:set ExitOK true;
:error false;
:exit;
}
}
@ -78,14 +74,12 @@
:if ([ $ScriptFromTerminal $ScriptName ] = true) do={
$LogPrint info $ScriptName ("System is already up to date.");
}
:set ExitOK true;
:error true;
:exit;
}
:if ([ :len ($Update->"latest-version") ] = 0) do={
$LogPrint info $ScriptName ("Received an empty version string from server.");
:set ExitOK true;
:error false;
:exit;
}
:local NumInstalled [ $VersionToNum ($Update->"installed-version") ];
@ -97,8 +91,7 @@
:if ($NumLatest < [ $VersionToNum "7.0" ]) do={
$LogPrint warning $ScriptName ("The version '" . ($Update->"latest-version") . "' is not a valid version.");
:set ExitOK true;
:error false;
:exit;
}
:if ($NumInstalled < $NumLatest) do={
@ -110,8 +103,7 @@
message=("Installing ALL versions automatically, including " . $Update->"latest-version" . \
"... Updating on " . $Identity . "..."); link=$Link; silent=true });
$DoUpdate $ScriptName;
:set ExitOK true;
:error true;
:exit;
}
:if ($SafeUpdatePatch = true && $NumInstalledFeature = $NumLatestFeature) do={
@ -121,8 +113,7 @@
message=("Version " . $Update->"latest-version" . " is a patch update for " . $Update->"channel" . \
", updating on " . $Identity . "..."); link=$Link; silent=true });
$DoUpdate $ScriptName;
:set ExitOK true;
:error true;
:exit;
}
:if ($SafeUpdateNeighbor = true) do={
@ -137,8 +128,7 @@
message=("Seen a neighbor (" . $Neighbor . ") running version " . $Update->"latest-version" . \
" from " . $Update->"channel" . ", updating on " . $Identity . "..."); link=$Link; silent=true });
$DoUpdate $ScriptName;
:set ExitOK true;
:error true;
:exit;
}
}
@ -159,8 +149,7 @@
message=("Version " . $Update->"latest-version" . " is considered safe for " . $Update->"channel" . \
", updating on " . $Identity . "..."); link=$Link; silent=true });
$DoUpdate $ScriptName;
:set ExitOK true;
:error true;
:exit;
}
}
@ -170,16 +159,14 @@
:if (([ /terminal/inkey timeout=60 ] % 32) = 25) do={
/system/package/update/set channel=stable;
$LogPrint info $ScriptName ("Switched to channel 'stable', please re-run!");
:set ExitOK true;
:error true;
:exit;
}
}
:put ("Do you want to install RouterOS version " . $Update->"latest-version" . "? [y/N]");
:if (([ /terminal/inkey timeout=60 ] % 32) = 25) do={
$DoUpdate $ScriptName;
:set ExitOK true;
:error true;
:exit;
} else={
:put "Canceled...";
}
@ -188,8 +175,7 @@
:if ($SentRouterosUpdateNotification = $Update->"latest-version") do={
$LogPrint info $ScriptName ("Already sent the RouterOS update notification for version " . \
$Update->"latest-version" . ".");
:set ExitOK true;
:error true;
:exit;
}
$SendNotification2 ({ origin=$ScriptName; \
@ -204,8 +190,7 @@
:if ($SentRouterosUpdateNotification = $Update->"latest-version") do={
$LogPrint info $ScriptName ("Already sent the RouterOS downgrade notification for version " . \
$Update->"latest-version" . ".");
:set ExitOK true;
:error true;
:exit;
}
$SendNotification2 ({ origin=$ScriptName; \
@ -218,5 +203,5 @@
:set SentRouterosUpdateNotification ($Update->"latest-version");
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -30,8 +29,7 @@
:global SymbolForNotification;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :len [ /caps-man/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
@ -96,5 +94,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -30,8 +29,7 @@
:global SymbolForNotification;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :len [ /interface/wireless/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
@ -97,5 +95,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -12,7 +12,6 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -31,8 +30,7 @@
:global SymbolForNotification;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :len [ /caps-man/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
@ -114,5 +112,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -30,8 +29,7 @@
:global SymbolForNotification;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :len [ /interface/wifi/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
@ -96,5 +94,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -32,8 +31,7 @@
:global WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -92,5 +90,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -32,8 +31,7 @@
:global WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -91,5 +89,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -12,7 +12,6 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -33,8 +32,7 @@
:global WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -107,5 +105,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -32,8 +31,7 @@
:global WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -92,5 +90,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -22,8 +21,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
@ -39,5 +37,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -22,8 +21,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
@ -39,5 +37,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -12,7 +12,6 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -23,8 +22,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
@ -44,5 +42,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -22,8 +21,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
@ -39,5 +37,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -9,7 +9,6 @@
# check DHCP leases and add/remove/update DNS entries
# https://rsc.eworm.de/doc/dhcp-to-dns.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -28,8 +27,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:local Ttl 5m;
@ -126,5 +124,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -4,7 +4,7 @@ Renew certificates and notify on expiration
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.17-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.19-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)

View file

@ -4,7 +4,7 @@ Forward log messages via notification
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.17-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.22beta1-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)

View file

@ -4,7 +4,7 @@ Import ssh keys for public key authentication
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.17-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.21-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
@ -38,9 +38,8 @@ import that key:
$SSHKeysImport "ssh-rsa AAAAB3Nza...QYZk8= user" admin;
The third part of the key (`user` in this example) is inherited as
`info` in RouterOS (or `key-owner` with RouterOS 7.20.x and before). Also
the `MD5` fingerprint is recorded, this helps to audit and verify the
available keys.
`info` in RouterOS. Also the `MD5` fingerprint is recorded, this helps
to audit and verify the available keys.
> **Info**: Use `ssh-keygen` to show a fingerprint of an existing public
> key file: `ssh-keygen -l -E md5 -f ~/.ssh/id_ed25519.pub`

View file

@ -8,7 +8,6 @@
# install firmware upgrade, and reboot
# https://rsc.eworm.de/doc/firmware-upgrade-reboot.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -20,21 +19,18 @@
:global VersionToNum;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:local RouterBoard [ /system/routerboard/get ];
:if ($RouterBoard->"current-firmware" = $RouterBoard->"upgrade-firmware") do={
$LogPrint info $ScriptName ("Current and upgrade firmware match with version " . \
$RouterBoard->"current-firmware" . ".");
:set ExitOK true;
:error true;
:exit;
}
:if ([ $VersionToNum ($RouterBoard->"current-firmware") ] > [ $VersionToNum ($RouterBoard->"upgrade-firmware") ]) do={
$LogPrint info $ScriptName ("Different firmware version is available, but it is a downgrade. Ignoring.");
:set ExitOK true;
:error true;
:exit;
}
:if ([ /system/routerboard/settings/get auto-upgrade ] = false) do={
@ -56,5 +52,5 @@
$LogPrint info $ScriptName ("Firmware upgrade successful, rebooting.");
/system/reboot;
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -8,7 +8,6 @@
# download, import and update firewall address-lists
# https://rsc.eworm.de/doc/fw-addr-lists.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -46,8 +45,7 @@
}
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -113,41 +111,40 @@
} else={
:set Address ([ :pick $Line 0 [ $FindDelim $Line ] ] . ($List->"cidr"));
}
:do {
:local Branch;
:if ($Address ~ "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}(/[0-9]{1,2})?\$") do={
:local Net $Address;
:local CIDR 32;
:local Slash [ :find $Address "/" ];
:if ([ :typeof $Slash ] = "num") do={
:set Net [ :toip [ :pick $Address 0 $Slash ] ]
:set CIDR [ :pick $Address ($Slash + 1) [ :len $Address ] ];
:set Address [ :tostr (([ :toip $Net ] & [ $NetMask4 $CIDR ]) . [ $IfThenElse ($CIDR < 32) ("/" . $CIDR) ]) ];
}
:set Branch [ $GetBranch $Address ];
:set ($IPv4Addresses->$Branch->$Address) $TimeOut;
:error true;
:local Branch;
:if ($Address ~ "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}(/[0-9]{1,2})?\$") do={
:local Net $Address;
:local CIDR 32;
:local Slash [ :find $Address "/" ];
:if ([ :typeof $Slash ] = "num") do={
:set Net [ :toip [ :pick $Address 0 $Slash ] ]
:set CIDR [ :pick $Address ($Slash + 1) [ :len $Address ] ];
:set Address [ :tostr (([ :toip $Net ] & [ $NetMask4 $CIDR ]) . [ $IfThenElse ($CIDR < 32) ("/" . $CIDR) ]) ];
}
:if ($Address ~ "^[0-9a-zA-Z]*:[0-9a-zA-Z:\\.]+(/[0-9]{1,3})?\$") do={
:local Net $Address;
:local CIDR 128;
:local Slash [ :find $Address "/" ];
:if ([ :typeof $Slash ] = "num") do={
:set Net [ :toip6 [ :pick $Address 0 $Slash ] ]
:set CIDR [ :pick $Address ($Slash + 1) [ :len $Address ] ];
}
:set Address (([ :toip6 $Net ] & [ $NetMask6 $CIDR ]) . "/" . $CIDR);
:set Branch [ $GetBranch $Address ];
:set ($IPv6Addresses->$Branch->$Address) $TimeOut;
:error true;
:set Branch [ $GetBranch $Address ];
:set ($IPv4Addresses->$Branch->$Address) $TimeOut;
:continue;
}
:if ($Address ~ "^[0-9a-zA-Z]*:[0-9a-zA-Z:\\.]+(/[0-9]{1,3})?\$") do={
:local Net $Address;
:local CIDR 128;
:local Slash [ :find $Address "/" ];
:if ([ :typeof $Slash ] = "num") do={
:set Net [ :toip6 [ :pick $Address 0 $Slash ] ]
:set CIDR [ :pick $Address ($Slash + 1) [ :len $Address ] ];
}
:if ($Address ~ "^[\\.a-zA-Z0-9-]+\\.[a-zA-Z]{2,}\$") do={
:set Branch [ $GetBranch $Address ];
:set ($IPv4Addresses->$Branch->$Address) $TimeOut;
:set ($IPv6Addresses->$Branch->$Address) $TimeOut;
:error true;
}
} on-error={ }
:set Address (([ :toip6 $Net ] & [ $NetMask6 $CIDR ]) . "/" . $CIDR);
:set Branch [ $GetBranch $Address ];
:set ($IPv6Addresses->$Branch->$Address) $TimeOut;
:continue;
}
:if ($Address ~ "^[\\.a-zA-Z0-9-]+\\.[a-zA-Z]{2,}\$") do={
:set Branch [ $GetBranch $Address ];
:set ($IPv4Addresses->$Branch->$Address) $TimeOut;
:set ($IPv6Addresses->$Branch->$Address) $TimeOut;
:continue;
}
}
}
@ -232,5 +229,5 @@
" - removed: " . [ $HumanReadableNum $CntRemove 1000 ]);
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -4,7 +4,7 @@
# Michael Gisbers <michael@gisbers.de>
# https://rsc.eworm.de/COPYING.md
#
# requires RouterOS, version=7.17
# requires RouterOS, version=7.19
# requires device-mode, fetch, scheduler
#
# global functions
@ -47,7 +47,6 @@
:global GetRandom20CharHex;
:global GetRandomNumber;
:global Grep;
:global HexToNum;
:global HumanReadableNum;
:global IfThenElse;
:global IsDefaultRouteReachable;
@ -131,7 +130,7 @@
:if ((($CertSettings->"builtin-trust-anchors") = "trusted" || \
($CertSettings->"builtin-trust-store") ~ $UseFor || \
($CertSettings->"builtin-trust-store") = "all") && \
[[ :parse (":return [ :len [ /certificate/builtin/find where common-name=\"" . $CommonName . "\" ] ]") ]] > 0) do={
[ :len [ /certificate/builtin/find where common-name=$CommonName ] ] > 0) do={
:return true;
}
@ -475,9 +474,8 @@
# simple macro to print error message on unintentional error
:set ExitError do={
:local ExitOK [ :tostr $1 ];
:local Name [ :tostr $2 ];
:local Error [ :tostr $3 ];
:local Name [ :tostr $1 ];
:local Error [ :tostr $2 ];
:global IfThenElse;
:global LogPrint;
@ -717,19 +715,6 @@
:return [];
}
# convert from hex (string) to num
:set HexToNum do={
:local Input [ :tostr $1 ];
:global HexToNum;
:if ([ :pick $Input 0 ] = "*") do={
:return [ $HexToNum [ :pick $Input 1 [ :len $Input ] ] ];
}
:return [ :tonum ("0x" . $Input) ];
}
# return human readable number
:set HumanReadableNum do={
:local Input [ :tonum $1 ];
@ -1302,105 +1287,103 @@
}
}
:do {
:if ($ScriptInfo->"ignore" = true) do={
$LogPrint debug $0 ("Ignoring script '" . $ScriptVal->"name" . "', as requested.");
:error true;
:if ($ScriptInfo->"ignore" = true) do={
$LogPrint debug $0 ("Ignoring script '" . $ScriptVal->"name" . "', as requested.");
:continue;
}
:local CheckSum ($CheckSums->($ScriptVal->"name"));
:if ([ :len ($ScriptInfo->"base-url") ] = 0 && [ :len ($ScriptInfo->"url-suffix") ] = 0 && \
[ :convert transform=md5 to=hex [ :tolf ($ScriptVal->"source") ] ] = $CheckSum) do={
$LogPrint debug $0 ("Checksum for script '" . $ScriptVal->"name" . "' matches, ignoring.");
:continue;
}
:if ([ :len ($ScriptInfo->"certificate") ] > 0) do={
:if ([ $CertificateAvailable ($ScriptInfo->"certificate") "fetch" ] = false) do={
$LogPrint warning $0 ("Downloading certificate failed, trying without.");
}
}
:onerror Err {
:local BaseUrl [ $EitherOr ($ScriptInfo->"base-url") $ScriptUpdatesBaseUrl ];
:local UrlSuffix [ $EitherOr ($ScriptInfo->"url-suffix") $ScriptUpdatesUrlSuffix ];
:local Url ($BaseUrl . $ScriptVal->"name" . ".rsc" . $UrlSuffix);
$LogPrint debug $0 ("Fetching script '" . $ScriptVal->"name" . "' from url: " . $Url);
:local Result [ /tool/fetch check-certificate=yes-without-crl \
http-header-field=({ [ $FetchUserAgentStr $0 ] }) $Url output=user as-value ];
:if ($Result->"status" = "finished") do={
:set SourceNew [ :tolf ($Result->"data") ];
}
} do={
$LogPrint warning $0 ("Failed fetching script '" . $ScriptVal->"name" . "': " . $Err);
:if ($Err != "Fetch failed with status 404") do={
:continue;
}
:local CheckSum ($CheckSums->($ScriptVal->"name"));
:if ($ScriptVal->"source" = "#!rsc by RouterOS\n") do={
$LogPrint warning $0 ("Removing dummy. Typo on installation?");
/system/script/remove $Script;
:continue;
}
:if ([ :len ($ScriptInfo->"base-url") ] = 0 && [ :len ($ScriptInfo->"url-suffix") ] = 0 && \
[ :convert transform=md5 to=hex [ :tolf ($ScriptVal->"source") ] ] = $CheckSum) do={
$LogPrint debug $0 ("Checksum for script '" . $ScriptVal->"name" . "' matches, ignoring.");
:error true;
[ :len $CheckSum ] = 0) do={
$LogPrintOnce warning $0 \
("Added the script manually? Skip updates with 'ignore=true' in comment.");
}
:continue;
}
:if ([ :len ($ScriptInfo->"certificate") ] > 0) do={
:if ([ $CertificateAvailable ($ScriptInfo->"certificate") "fetch" ] = false) do={
$LogPrint warning $0 ("Downloading certificate failed, trying without.");
}
}
:if ([ :len $SourceNew ] = 0) do={
$LogPrint debug $0 ("No update for script '" . $ScriptVal->"name" . "'.");
:continue;
}
:onerror Err {
:local BaseUrl [ $EitherOr ($ScriptInfo->"base-url") $ScriptUpdatesBaseUrl ];
:local UrlSuffix [ $EitherOr ($ScriptInfo->"url-suffix") $ScriptUpdatesUrlSuffix ];
:local Url ($BaseUrl . $ScriptVal->"name" . ".rsc" . $UrlSuffix);
$LogPrint debug $0 ("Fetching script '" . $ScriptVal->"name" . "' from url: " . $Url);
:local Result [ /tool/fetch check-certificate=yes-without-crl \
http-header-field=({ [ $FetchUserAgentStr $0 ] }) $Url output=user as-value ];
:if ($Result->"status" = "finished") do={
:set SourceNew [ :tolf ($Result->"data") ];
}
} do={
$LogPrint warning $0 ("Failed fetching script '" . $ScriptVal->"name" . "': " . $Err);
:if ($Err != "Fetch failed with status 404") do={
:error false;
}
:local SourceCRLF [ :tocrlf $SourceNew ];
:if ($SourceNew = $ScriptVal->"source" || $SourceCRLF = $ScriptVal->"source") do={
$LogPrint debug $0 ("Script '" . $ScriptVal->"name" . "' did not change.");
:continue;
}
:if ($ScriptVal->"source" = "#!rsc by RouterOS\n") do={
$LogPrint warning $0 ("Removing dummy. Typo on installation?");
/system/script/remove $Script;
:error false;
}
:if ([ :len ($ScriptInfo->"base-url") ] = 0 && [ :len ($ScriptInfo->"url-suffix") ] = 0 && \
[ :len $CheckSum ] = 0) do={
$LogPrintOnce warning $0 \
("Added the script manually? Skip updates with 'ignore=true' in comment.");
}
:error false;
}
:if ([ :pick $SourceNew 0 18 ] != "#!rsc by RouterOS\n") do={
$LogPrint warning $0 ("Looks like new script '" . $ScriptVal->"name" . \
"' is not valid (missing shebang). Ignoring!");
:continue;
}
:if ([ :len $SourceNew ] = 0) do={
$LogPrint debug $0 ("No update for script '" . $ScriptVal->"name" . "'.");
:error false;
}
:local RequiredROS ([ $ParseKeyValueStore [ $Grep $SourceNew ("\23 requires RouterOS, ") ] ]->"version");
:if ([ $RequiredRouterOS $0 [ $EitherOr $RequiredROS "0.0" ] false ] = false) do={
$LogPrintOnce warning $0 ("The script '" . $ScriptVal->"name" . "' requires RouterOS " . \
$RequiredROS . ", which is not met by your installation. Ignoring!");
:continue;
}
:local SourceCRLF [ :tocrlf $SourceNew ];
:if ($SourceNew = $ScriptVal->"source" || $SourceCRLF = $ScriptVal->"source") do={
$LogPrint debug $0 ("Script '" . $ScriptVal->"name" . "' did not change.");
:error false;
:local RequiredDM [ $ParseKeyValueStore [ $Grep $SourceNew ("\23 requires device-mode, ") ] ];
:local MissingDM ({});
:foreach Feature,Value in=$RequiredDM do={
:if ([ :typeof ($DeviceMode->$Feature) ] = "bool" && ($DeviceMode->$Feature) = false) do={
:set MissingDM ($MissingDM, $Feature);
}
}
:if ([ :len $MissingDM ] > 0) do={
$LogPrintOnce warning $0 ("The script '" . $ScriptVal->"name" . "' requires disabled " . \
"device-mode features (" . [ :tostr $MissingDM ] . "). Ignoring!");
:continue;
}
:if ([ :pick $SourceNew 0 18 ] != "#!rsc by RouterOS\n") do={
$LogPrint warning $0 ("Looks like new script '" . $ScriptVal->"name" . \
"' is not valid (missing shebang). Ignoring!");
:error false;
}
:if ([ $ValidateSyntax $SourceNew ] = false) do={
$LogPrint warning $0 ("Syntax validation for script '" . $ScriptVal->"name" . "' failed! Ignoring!");
:continue;
}
:local RequiredROS ([ $ParseKeyValueStore [ $Grep $SourceNew ("\23 requires RouterOS, ") ] ]->"version");
:if ([ $RequiredRouterOS $0 [ $EitherOr $RequiredROS "0.0" ] false ] = false) do={
$LogPrintOnce warning $0 ("The script '" . $ScriptVal->"name" . "' requires RouterOS " . \
$RequiredROS . ", which is not met by your installation. Ignoring!");
:error false;
}
:local RequiredDM [ $ParseKeyValueStore [ $Grep $SourceNew ("\23 requires device-mode, ") ] ];
:local MissingDM ({});
:foreach Feature,Value in=$RequiredDM do={
:if ([ :typeof ($DeviceMode->$Feature) ] = "bool" && ($DeviceMode->$Feature) = false) do={
:set MissingDM ($MissingDM, $Feature);
}
}
:if ([ :len $MissingDM ] > 0) do={
$LogPrintOnce warning $0 ("The script '" . $ScriptVal->"name" . "' requires disabled " . \
"device-mode features (" . [ :tostr $MissingDM ] . "). Ignoring!");
:error false;
}
:if ([ $ValidateSyntax $SourceNew ] = false) do={
$LogPrint warning $0 ("Syntax validation for script '" . $ScriptVal->"name" . "' failed! Ignoring!");
:error false;
}
$LogPrint info $0 ("Updating script: " . $ScriptVal->"name");
/system/script/set owner=($ScriptVal->"name") \
source=[ $IfThenElse ($ScriptUpdatesCRLF = true) $SourceCRLF $SourceNew ] $Script;
:if ($ScriptVal->"name" = "global-config" || \
$ScriptVal->"name" = "global-functions" || \
$ScriptVal->"name" ~ ("^mod/.")) do={
:set ReloadGlobal true;
}
} on-error={ }
$LogPrint info $0 ("Updating script: " . $ScriptVal->"name");
/system/script/set owner=($ScriptVal->"name") \
source=[ $IfThenElse ($ScriptUpdatesCRLF = true) $SourceCRLF $SourceNew ] $Script;
:if ($ScriptVal->"name" = "global-config" || \
$ScriptVal->"name" = "global-functions" || \
$ScriptVal->"name" ~ ("^mod/.")) do={
:set ReloadGlobal true;
}
}
:if ($ReloadGlobal = true) do={
@ -1517,7 +1500,7 @@
:set GlobalConfigMigration;
}
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# lock script against multiple invocation
@ -1663,7 +1646,7 @@
$SendNotification2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 });
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# send notification via NotificationFunctions - expects one array argument

View file

@ -9,7 +9,6 @@
# track gps data by sending json data to http server
# https://rsc.eworm.de/doc/gps-track.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -25,8 +24,7 @@
:global WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -49,5 +47,5 @@
$LogPrint debug $ScriptName ("GPS data not valid.");
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -12,7 +12,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -25,8 +24,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:local DHCPServers ({});
@ -76,5 +74,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -13,7 +13,6 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -26,8 +25,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:local DHCPServers ({});
@ -83,5 +81,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -12,7 +12,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -25,8 +24,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:local DHCPServers ({});
@ -76,5 +74,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -27,14 +26,12 @@
:local UserName $username;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :typeof $MacAddress ] = "nothing" || [ :typeof $UserName ] = "nothing") do={
$LogPrint error $ScriptName ("This script is supposed to run from hotspot on login.");
:set ExitOK true;
:error false;
:exit;
}
:local Date [ /system/clock/get date ];
@ -61,8 +58,7 @@
:if ($Template->"action" = "reject") do={
$LogPrint info $ScriptName ("Ignoring login for hotspot '" . $Hotspot . "'.");
:set ExitOK true;
:error true;
:exit;
}
# allow login page to load
@ -101,5 +97,5 @@
:delay 2s;
/caps-man/access-list/set $Entry action=accept;
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -12,7 +12,6 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -28,14 +27,12 @@
:local UserName $username;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :typeof $MacAddress ] = "nothing" || [ :typeof $UserName ] = "nothing") do={
$LogPrint error $ScriptName ("This script is supposed to run from hotspot on login.");
:set ExitOK true;
:error false;
:exit;
}
:local Date [ /system/clock/get date ];
@ -68,8 +65,7 @@
:if ($Template->"action" = "reject") do={
$LogPrint info $ScriptName ("Ignoring login for hotspot '" . $Hotspot . "'.");
:set ExitOK true;
:error true;
:exit;
}
# allow login page to load
@ -121,5 +117,5 @@
/caps-man/access-list/set $Entry action=accept;
/interface/wifi/access-list/set $Entry action=accept;
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
#
# !! Do not edit this file, it is generated from template!
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -27,14 +26,12 @@
:local UserName $username;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :typeof $MacAddress ] = "nothing" || [ :typeof $UserName ] = "nothing") do={
$LogPrint error $ScriptName ("This script is supposed to run from hotspot on login.");
:set ExitOK true;
:error false;
:exit;
}
:local Date [ /system/clock/get date ];
@ -61,8 +58,7 @@
:if ($Template->"action" = "reject") do={
$LogPrint info $ScriptName ("Ignoring login for hotspot '" . $Hotspot . "'.");
:set ExitOK true;
:error true;
:exit;
}
# allow login page to load
@ -98,5 +94,5 @@
:delay 2s;
/interface/wifi/access-list/set $Entry action=accept;
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -9,7 +9,6 @@
# and add/remove/update DNS entries from IPSec mode-config
# https://rsc.eworm.de/doc/ipsec-to-dns.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -28,8 +27,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:local Zone \
@ -80,5 +78,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -8,7 +8,6 @@
# update firewall and dns settings on IPv6 prefix change
# https://rsc.eworm.de/doc/ipv6-update.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -25,26 +24,22 @@
:local PdValid $"pd-valid";
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :typeof $NaAddress ] = "str") do={
$LogPrint info $ScriptName ("An address (" . $NaAddress . ") was acquired, not a prefix. Ignoring.");
:set ExitOK true;
:error false;
:exit;
}
:if ([ :typeof $PdPrefix ] = "nothing" || [ :typeof $PdValid ] = "nothing") do={
$LogPrint error $ScriptName ("This script is supposed to run from ipv6 dhcp-client.");
:set ExitOK true;
:error false;
:exit;
}
:if ($PdValid != 1) do={
$LogPrint info $ScriptName ("The prefix " . $PdPrefix . " is no longer valid. Ignoring.");
:set ExitOK true;
:error false;
:exit;
}
:local Pool [ /ipv6/pool/get [ find where prefix=$PdPrefix ] name ];
@ -103,5 +98,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -8,7 +8,6 @@
# run scripts on DHCP lease
# https://rsc.eworm.de/doc/lease-script.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -26,22 +25,19 @@
[ :typeof $leaseServerName ] = "nothing" || \
[ :typeof $leaseBound ] = "nothing") do={
$LogPrint error $ScriptName ("This script is supposed to run from ip dhcp-server.");
:set ExitOK true;
:error false;
:exit;
}
$LogPrint debug $ScriptName ("DHCP Server " . $leaseServerName . " " . [ $IfThenElse ($leaseBound = 0) \
"de" "" ] . "assigned lease " . $leaseActIP . " to " . $leaseActMAC);
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :len [ /system/script/job/find where script=$ScriptName ] ] > 1) do={
$LogPrint debug $ScriptName ("More invocations are waiting, exiting early.");
:set ExitOK true;
:error true;
:exit;
}
:local RunOrder ({});
@ -61,5 +57,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -3,12 +3,11 @@
# Copyright (c) 2020-2026 Christian Hesse <mail@eworm.de>
# https://rsc.eworm.de/COPYING.md
#
# requires RouterOS, version=7.17
# requires RouterOS, version=7.22beta1
#
# forward log messages via notification
# https://rsc.eworm.de/doc/log-forward.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -24,7 +23,6 @@
:global LogForwardRateLimit;
:global EitherOr;
:global HexToNum;
:global IfThenElse;
:global LogForwardFilterLogForwarding;
:global LogPrint;
@ -34,8 +32,11 @@
:global SymbolForNotification;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :typeof $LogForwardLast ] = "nothing") do={
:set LogForwardLast false;
}
:if ([ :typeof $LogForwardRateLimit ] = "nothing") do={
@ -45,13 +46,11 @@
:if ($LogForwardRateLimit > 30) do={
:set LogForwardRateLimit ($LogForwardRateLimit - 1);
$LogPrint info $ScriptName ("Rate limit in action, not forwarding logs, if any!");
:set ExitOK true;
:error false;
:exit;
}
:local Count 0;
:local Duplicates false;
:local Last [ $IfThenElse ([ :len $LogForwardLast ] > 0) [ $HexToNum $LogForwardLast ] -1 ];
:local Messages "";
:local Warning false;
:local MessageVal;
@ -63,37 +62,33 @@
:set LogForwardIncludeMessage [ $EitherOr $LogForwardIncludeMessage [] ];
:local LogAll [ /log/find ];
:local MaxId ($LogAll->([ :len $LogAll ] - 1));
:local MaxNum [ $HexToNum $MaxId ];
:local Max ($LogAll->([ :len $LogAll ] - 1));
:local LogForwardFilterLogForwardingCached [ $EitherOr [ $LogForwardFilterLogForwarding ] ("\$^") ];
:foreach Message in=[ /log/find where (!(message="") and \
!(message~$LogForwardFilterLogForwardingCached) and \
!(topics~$LogForwardFilter) and !(message~$LogForwardFilterMessage)) or \
topics~$LogForwardInclude or message~$LogForwardIncludeMessage ] do={
:foreach Message in=[ /log/find where .id>$LogForwardLast and .id<=$Max and \
((!(message="") and !(message~$LogForwardFilterLogForwardingCached) and \
!(topics~$LogForwardFilter) and !(message~$LogForwardFilterMessage)) or \
topics~$LogForwardInclude or message~$LogForwardIncludeMessage) ] do={
:set MessageVal [ /log/get $Message ];
:local Bullet "information";
:local Current [ $HexToNum ($MessageVal->".id") ];
:if ($Last < $Current && $Current <= $MaxNum) do={
:local DupCount ($MessageDups->($MessageVal->"message"));
:if ($MessageVal->"topics" ~ "(warning)") do={
:set Warning true;
:set Bullet "large-orange-circle";
}
:if ($MessageVal->"topics" ~ "(emergency|alert|critical|error)") do={
:set Warning true;
:set Bullet "large-red-circle";
}
:if ($DupCount < 3) do={
:set Messages ($Messages . "\n" . [ $SymbolForNotification $Bullet ] . \
$MessageVal->"time" . " " . [ :tostr ($MessageVal->"topics") ] . " " . $MessageVal->"message");
} else={
:set Duplicates true;
}
:set ($MessageDups->($MessageVal->"message")) ($DupCount + 1);
:set Count ($Count + 1);
:local DupCount ($MessageDups->($MessageVal->"message"));
:if ($MessageVal->"topics" ~ "(warning)") do={
:set Warning true;
:set Bullet "large-orange-circle";
}
:if ($MessageVal->"topics" ~ "(emergency|alert|critical|error)") do={
:set Warning true;
:set Bullet "large-red-circle";
}
:if ($DupCount < 3) do={
:set Messages ($Messages . "\n" . [ $SymbolForNotification $Bullet ] . \
$MessageVal->"time" . " " . [ :tostr ($MessageVal->"topics") ] . " " . $MessageVal->"message");
} else={
:set Duplicates true;
}
:set ($MessageDups->($MessageVal->"message")) ($DupCount + 1);
:set Count ($Count + 1);
}
:if ($Count > 0) do={
@ -111,7 +106,7 @@
:set LogForwardRateLimit [ $MAX 0 ($LogForwardRateLimit - 1) ];
}
:set LogForwardLast $MaxId;
:set LogForwardLast $Max;
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -66,5 +66,5 @@
/interface/ethernet/enable $InterfaceReEnable;
}
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }

View file

@ -75,5 +75,5 @@
/interface/ethernet/enable $InterfaceReEnable;
}
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }

View file

@ -17,7 +17,7 @@
:put [ :tocrlf [ $InspectVarReturn $1 ] ];
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# inspect variable and return formatted string

View file

@ -28,7 +28,7 @@
[ $FormatLine "HostMax" ($Values->"hostmax") ] . "\n" . \
[ $FormatLine "Broadcast" ($Values->"broadcast") ]) ];
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# calculate and return netmask, network, min host, max host and broadcast

View file

@ -146,7 +146,7 @@
/system/scheduler/set interval=(($SchedVal->"run-count") . "m") \
comment="Waiting for retry..." $Scheduler;
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# generate filter for log-forward
@ -274,7 +274,7 @@
$SendEMail2 ({ origin=$0; subject=$1; message=$2; link=$3 });
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# send notification via e-mail - expects one array argument

View file

@ -54,7 +54,7 @@
:set GotifyQueue;
}
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# send notification via Gotify - expects one array argument
@ -126,7 +126,7 @@
$SendGotify2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 });
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# send notification via Gotify - expects one array argument

View file

@ -59,7 +59,7 @@
:set MatrixQueue;
}
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# send notification via Matrix - expects one array argument
@ -172,7 +172,7 @@
$SendMatrix2 ({ origin=$0; subject=$1; message=$2; link=$3 });
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# send notification via Matrix - expects one array argument

View file

@ -53,7 +53,7 @@
:set NtfyQueue;
}
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# send notification via ntfy - expects one array argument
@ -148,7 +148,7 @@
$SendNtfy2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 });
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# send notification via ntfy - expects one array argument

View file

@ -62,7 +62,7 @@
:set TelegramQueue;
}
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# get the chat id
@ -101,7 +101,7 @@
$LogPrint info $0 ("The thread id is: " . ($Message->"message_thread_id"));
}
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# send notification via telegram - expects one array argument
@ -237,7 +237,7 @@
$SendTelegram2 ({ origin=$0; subject=$1; message=$2; link=$3; silent=$4 });
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# send notification via telegram - expects one array argument

View file

@ -52,5 +52,5 @@
:return true;
}
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }

View file

@ -3,7 +3,7 @@
# Copyright (c) 2020-2026 Christian Hesse <mail@eworm.de>
# https://rsc.eworm.de/COPYING.md
#
# requires RouterOS, version=7.17
# requires RouterOS, version=7.21
#
# import ssh keys for public key authentication
# https://rsc.eworm.de/doc/mod/ssh-keys-import.md
@ -40,9 +40,8 @@
:local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex ($KeyVal->1) ];
:local RegEx ("\\bmd5=" . $FingerPrintMD5 . "\\b");
:if ([ :len [ /user/ssh-keys/find where user=$User \
(key-owner~$RegEx or info~$RegEx) ] ] > 0) do={
info~("\\bmd5=" . $FingerPrintMD5 . "\\b") ] ] > 0) do={
$LogPrint warning $0 ("The ssh public key (MD5:" . $FingerPrintMD5 . \
") is already available for user '" . $User . "'.");
:return false;
@ -68,7 +67,7 @@
:return false;
}
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
# import keys from a file
@ -110,5 +109,5 @@
}
}
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }

View file

@ -9,7 +9,6 @@
# act on multiple mode and reset button presses
# https://rsc.eworm.de/doc/mode-button.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -83,7 +82,7 @@
$LogPrint info $FuncName ("No action defined for " . $Count . " mode-button presses.");
}
} do={
:global ExitError; $ExitError false $0 $Err;
:global ExitError; $ExitError $0 $Err;
} }
/system/scheduler/add name="_ModeButtonScheduler" \
on-event=":global ModeButtonScheduler; \$ModeButtonScheduler;" interval=3s;
@ -92,5 +91,5 @@
/system/scheduler/set $Scheduler start-time=[ /system/clock/get time ];
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -3,13 +3,12 @@
# Copyright (c) 2022-2026 Christian Hesse <mail@eworm.de>
# https://rsc.eworm.de/COPYING.md
#
# requires RouterOS, version=7.17
# requires RouterOS, version=7.22beta1
# requires device-mode, fetch
#
# monitor and manage dns/doh with netwatch
# https://rsc.eworm.de/doc/netwatch-dns.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -26,15 +25,13 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:local SettleTime (5m30s - [ /system/resource/get uptime ]);
:if ($SettleTime > 0s) do={
$LogPrint info $ScriptName ("System just booted, giving netwatch " . $SettleTime . " to settle.");
:set ExitOK true;
:error true;
:exit;
}
:local DnsServers ({});
@ -89,8 +86,7 @@
:if ($DohCurrent = $HostInfo->"doh-url" && [ $IsDNSResolving ] = true) do={
$LogPrint debug $ScriptName ("Current DoH server is still up and resolving: " . $DohCurrent);
:set ExitOK true;
:error true;
:exit;
}
:set ($DohServers->[ :len $DohServers ]) $HostInfo;
@ -135,8 +131,7 @@
}
/ip/dns/cache/flush;
$LogPrint info $ScriptName ("Setting DoH server: " . ($DohServer->"doh-url"));
:set ExitOK true;
:error true;
:exit;
} else={
$LogPrint warning $ScriptName ("Received unexpected response from DoH server: " . \
($DohServer->"doh-url"));
@ -144,5 +139,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -8,7 +8,6 @@
# monitor netwatch and send notifications
# https://rsc.eworm.de/doc/netwatch-notify.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -80,8 +79,7 @@
}
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:local ScriptFromTerminalCached [ $ScriptFromTerminal $ScriptName ];
@ -225,5 +223,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -8,7 +8,6 @@
# visualize ospf instance state via leds
# https://rsc.eworm.de/doc/ospf-to-leds.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -20,8 +19,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:foreach Instance in=[ /routing/ospf/instance/find where comment~"^ospf-to-leds," ] do={
@ -45,5 +43,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -9,7 +9,6 @@
# download packages and reboot for installation
# https://rsc.eworm.de/doc/packages-update.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -59,28 +58,24 @@
}
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ :len [ /system/scheduler/find where name="running-from-backup-partition" ] ] > 0) do={
$LogPrint warning $ScriptName ("Running from backup partition, refusing to act.");
:set ExitOK true;
:error false;
:exit;
}
:local Update [ /system/package/update/get ];
:if ([ :typeof ($Update->"latest-version") ] = "nothing") do={
$LogPrint warning $ScriptName ("Latest version is not known.");
:set ExitOK true;
:error false;
:exit;
}
:if ($Update->"installed-version" = $Update->"latest-version") do={
$LogPrint info $ScriptName ("Version " . $Update->"latest-version" . " is already installed.");
:set ExitOK true;
:error true;
:exit;
}
:local RunOrder ({});
@ -111,13 +106,11 @@
$LogPrint info $ScriptName ("User requested to continue anyway.");
} else={
$LogPrint info $ScriptName ("Canceled update...");
:set ExitOK true;
:error false;
:exit;
}
} else={
$LogPrint warning $ScriptName ("Canceled non-interactive update.");
:set ExitOK true;
:error false;
:exit;
}
}
}
@ -136,8 +129,7 @@
}
} else={
$LogPrint warning $ScriptName ("Not installing downgrade automatically.");
:set ExitOK true;
:error false;
:exit;
}
}
@ -145,8 +137,7 @@
:local PkgName [ /system/package/get $Package name ];
:if ([ $DownloadPackage $PkgName ($Update->"latest-version") ] = false) do={
$LogPrint error $ScriptName ("Download for package " . $PkgName . " failed, update aborted.");
:set ExitOK true;
:error false;
:exit;
}
}
@ -160,14 +151,12 @@
:put "Do you want to (s)chedule reboot or (r)eboot now? [s/R]";
:if (([ /terminal/inkey timeout=60 ] % 32) = 19) do={
$Schedule $ScriptName;
:set ExitOK true;
:error true;
:exit;
}
} else={
:if ($PackagesUpdateDeferReboot = true || [ :totime $PackagesUpdateDeferReboot ] >= 1d) do={
$Schedule $ScriptName;
:set ExitOK true;
:error true;
:exit;
}
}
@ -175,5 +164,5 @@
:delay 1s;
/system/reboot;
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -8,7 +8,6 @@
# run scripts on ppp up
# https://rsc.eworm.de/doc/ppp-on-up.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -21,8 +20,7 @@
:if ([ :typeof $Interface ] = "nothing") do={
$LogPrint error $ScriptName ("This script is supposed to run from ppp on-up script hook.");
:set ExitOK true;
:error false;
:exit;
}
:local IntName [ /interface/get $Interface name ];
@ -40,5 +38,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -8,7 +8,6 @@
# run action on received SMS
# https://rsc.eworm.de/doc/sms-action.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -24,8 +23,7 @@
:if ([ :typeof $Action ] = "nothing") do={
$LogPrint error $ScriptName ("This script is supposed to run from SMS hook with action=...");
:set ExitOK true;
:error false;
:exit;
}
:local Code ($SmsAction->$Action);
@ -37,5 +35,5 @@
$LogPrint warning $ScriptName ("The code for action '" . $Action . "' failed syntax validation!");
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -9,7 +9,6 @@
# forward SMS to e-mail
# https://rsc.eworm.de/doc/sms-forward.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -29,14 +28,12 @@
:global WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ /tool/sms/get receive-enabled ] = false) do={
$LogPrintOnce warning $ScriptName ("Receiving of SMS is not enabled.");
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -45,8 +42,7 @@
:if ([ /interface/lte/get ($Settings->"port") running ] != true) do={
$LogPrint info $ScriptName ("The LTE interface is not in running state, skipping.");
:set ExitOK true;
:error true;
:exit;
}
# forward SMS in a loop
@ -107,5 +103,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -3,13 +3,12 @@
# Copyright (c) 2023-2026 Christian Hesse <mail@eworm.de>
# https://rsc.eworm.de/COPYING.md
#
# requires RouterOS, version=7.17
# requires RouterOS, version=7.22beta1
# requires device-mode, fetch
#
# use Telegram to chat with your Router and send commands
# https://rsc.eworm.de/doc/telegram-chat.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -48,8 +47,7 @@
:global WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
$WaitFullyConnected;
@ -63,8 +61,7 @@
:if ([ $CertificateAvailable "Go Daddy Root Certificate Authority - G2" "fetch" ] = false) do={
$LogPrint warning $ScriptName ("Downloading required certificate failed.");
:set ExitOK true;
:error false;
:exit;
}
$RandomDelay $TelegramRandomDelay;
@ -89,8 +86,7 @@
:if ($Data = false) do={
$LogPrint warning $ScriptName ("Failed getting updates.");
:set ExitOK true;
:error false;
:exit;
}
:local JSON [ :deserialize from=json value=$Data ];
@ -119,7 +115,6 @@
}
:if ($Trusted = true) do={
:local Done false;
:if ($Command = "?") do={
$LogPrint info $ScriptName ("Sending notice for update " . $UpdateID . ".");
$SendTelegram2 ({ origin=$ScriptName; chatid=($Chat->"id"); silent=true; \
@ -127,9 +122,9 @@
subject=([ $SymbolForNotification "speech-balloon" ] . "Telegram Chat"); \
message=([ $IfThenElse ([ :len ($From->"first_name") ] > 0) ("Hello " . ($From->"first_name") . "!\n\n") ] . \
"Online" . [ $IfThenElse $TelegramChatActive " (and active!)" ] . ", awaiting your commands!") });
:set Done true;
:continue;
}
:if ($Done = false && [ :pick $Command 0 1 ] = "!") do={
:if ([ :pick $Command 0 1 ] = "!") do={
:if ($Command ~ ("^! *(" . [ $EscapeForRegEx $Identity ] . "|@" . $TelegramChatGroups . ")\$")) do={
:set TelegramChatActive true;
} else={
@ -137,17 +132,16 @@
}
$LogPrint info $ScriptName ("Now " . [ $IfThenElse $TelegramChatActive "active" "passive" ] . \
" from update " . $UpdateID . "!");
:set Done true;
:continue;
}
:if ($Done = false && ($IsMyReply = 1 || ($IsAnyReply = false && \
:if (($IsMyReply = 1 || ($IsAnyReply = false && \
$TelegramChatActive = true)) && [ :len $Command ] > 0) do={
:if ([ $ValidateSyntax $Command ] = true) do={
:local State "";
:local File ("tmpfs/telegram-chat/" . [ $GetRandom20CharAlNum 6 ]);
:if ([ $MkDir "tmpfs/telegram-chat" ] = false) do={
$LogPrint error $ScriptName ("Failed creating directory!");
:set ExitOK true;
:error false;
:exit;
}
$LogPrint info $ScriptName ("Running command from update " . $UpdateID . ": " . $Command);
:execute script=(":do {\n" . $Command . "\n} on-error={ /file/add name=\"" . $File . ".failed\" };" . \
@ -197,5 +191,5 @@
:set TelegramChatOffset ([ :pick $TelegramChatOffset 1 3 ], \
[ $IfThenElse ($UpdateID >= $TelegramChatOffset->2) ($UpdateID + 1) ($TelegramChatOffset->2) ]);
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -9,7 +9,6 @@
# ipsec remote peer
# https://rsc.eworm.de/doc/update-gre-address.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -21,8 +20,7 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
/interface/gre/set remote-address=0.0.0.0 disabled=yes [ find where !running !disabled ];
@ -42,5 +40,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}

View file

@ -11,7 +11,6 @@
# update local address of tunnelbroker interface
# https://rsc.eworm.de/doc/update-tunnelbroker.md
:local ExitOK false;
:onerror Err {
:global GlobalConfigReady; :global GlobalFunctionsReady;
:retry { :if ($GlobalConfigReady != true || $GlobalFunctionsReady != true) \
@ -24,14 +23,12 @@
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set ExitOK true;
:error false;
:exit;
}
:if ([ $CertificateAvailable "Starfield Root Certificate Authority - G2" "fetch" ] = false) do={
$LogPrint error $ScriptName ("Downloading required certificate failed.");
:set ExitOK true;
:error false;
:exit;
}
:foreach Interface in=[ /interface/6to4/find where comment~"^tunnelbroker" !disabled ] do={
@ -54,8 +51,7 @@
:if (!($Data ~ "^(good|nochg) ")) do={
$LogPrint error $ScriptName ("Failed sending the local address to tunnelbroker or unexpected response!");
:set ExitOK true;
:error false;
:exit;
}
:local PublicAddress [ :pick $Data ([ :find $Data " " ] + 1) [ :find $Data "\n" ] ];
@ -70,5 +66,5 @@
}
}
} do={
:global ExitError; $ExitError $ExitOK [ :jobname ] $Err;
:global ExitError; $ExitError [ :jobname ] $Err;
}