Merge branch 'ros-v7-path-syntax' into next

This commit is contained in:
Christian Hesse 2022-05-12 11:04:43 +02:00
commit df547b87a4
130 changed files with 684 additions and 714 deletions

View file

@ -7,35 +7,30 @@ Initial commands
> not aware of the procedure please follow > not aware of the procedure please follow
> [the long way in detail](README.md#the-long-way-in-detail). > [the long way in detail](README.md#the-long-way-in-detail).
One extra step is required if you run RouterOS v6: Run the complete base installation:
:global ScriptUpdatesUrlSuffix "\?h=routeros-v6";
Then 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;
/ tool fetch "https://git.eworm.de/cgit/routeros-scripts/plain/certs/R3.pem" dst-path="letsencrypt-R3.pem" as-value;
:delay 1s; :delay 1s;
/ certificate import file-name=letsencrypt-R3.pem passphrase=""; /certificate/import file-name=letsencrypt-R3.pem passphrase="";
:if ([ :len [ / certificate find where fingerprint="67add1166b020ae61b8f5fc96813c04c2aa589960796865572a3c7e737613dfd" or fingerprint="96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6" ] ] != 2) do={ :if ([ :len [ /certificate/find where fingerprint="67add1166b020ae61b8f5fc96813c04c2aa589960796865572a3c7e737613dfd" or fingerprint="96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6" ] ] != 2) do={
:error "Something is wrong with your certificates!"; :error "Something is wrong with your certificates!";
}; };
/ file remove "letsencrypt-R3.pem"; /file/remove "letsencrypt-R3.pem";
:delay 1s; :delay 1s;
:foreach Script in={ "global-config"; "global-config-overlay"; "global-functions" } do={ :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) output=user as-value]->"data");
}; };
/ system script { run global-config; run global-functions; }; /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; }"; /system/scheduler/add name="global-scripts" start-time=startup on-event="/system/script { run global-config; run global-functions; }";
:global CertificateNameByCN; :global CertificateNameByCN;
$CertificateNameByCN "R3"; $CertificateNameByCN "R3";
$CertificateNameByCN "ISRG Root X1"; $CertificateNameByCN "ISRG Root X1";
} };
Optional to update the scripts automatically: Optional to update the scripts automatically:
/ system scheduler add name="ScriptInstallUpdate" start-time=startup interval=1d on-event=":global ScriptInstallUpdate; \$ScriptInstallUpdate;"; /system/scheduler/add name="ScriptInstallUpdate" start-time=startup interval=1d on-event=":global ScriptInstallUpdate; \$ScriptInstallUpdate;";
--- ---
[◀ Go back to main README](README.md) [◀ Go back to main README](README.md)

View file

@ -15,11 +15,11 @@ all: $(CAPSMAN) $(LOCAL) $(HTML)
markdown $< | sed 's/href="\([-_\./[:alnum:]]*\)\.md"/href="\1.html"/g' > $@ markdown $< | sed 's/href="\([-_\./[:alnum:]]*\)\.md"/href="\1.html"/g' > $@
%.local: %.template Makefile %.local: %.template Makefile
sed -e '/\/ caps-man/d' -e 's|%PATH%|interface wireless|' -e 's|%TEMPL%|$(suffix $@)|' \ sed -e '/\/caps-man/d' -e 's|%PATH%|interface\/wireless|' -e 's|%TEMPL%|$(suffix $@)|' \
-e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \ -e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \
< $< > $@ < $< > $@
%.capsman: %.template Makefile %.capsman: %.template Makefile
sed -e '/\/ interface wireless/d' -e 's/%PATH%/caps-man/' -e 's/%TEMPL%/$(suffix $@)/' \ sed -e '/\/interface\/wireless/d' -e 's/%PATH%/caps-man/' -e 's/%TEMPL%/$(suffix $@)/' \
-e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \ -e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \
< $< > $@ < $< > $@

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Before After
Before After

View file

@ -1,3 +1,3 @@
#!rsc by RouterOS #!rsc by RouterOS
:put ("Hello World from " . [ / system identity get name ] . "!"); :put ("Hello World from " . [ /system/identity/get name ] . "!");

View file

@ -23,6 +23,9 @@ Make sure to install latest updates before you begin.
Specific scripts may require even newer RouterOS version. Specific scripts may require even newer RouterOS version.
> **Info**: The `main` branch is now RouterOS v7 only. If you are still
> running RouterOS v6 switch to `routeros-v6` branch!
Initial setup Initial setup
------------- -------------
@ -50,7 +53,7 @@ download the certificates. If you intend to download the scripts from a
different location (for example from github.com) install the corresponding different location (for example from github.com) install the corresponding
certificate chain. certificate chain.
/ tool fetch "https://git.eworm.de/cgit/routeros-scripts/plain/certs/R3.pem" dst-path="letsencrypt-R3.pem"; /tool/fetch "https://git.eworm.de/cgit/routeros-scripts/plain/certs/R3.pem" dst-path="letsencrypt-R3.pem";
![screenshot: download certs](README.d/01-download-certs.avif) ![screenshot: download certs](README.d/01-download-certs.avif)
@ -63,16 +66,16 @@ files to your MikroTik device.
Then we import the certificates. Then we import the certificates.
/ certificate import file-name=letsencrypt-R3.pem passphrase=""; /certificate/import file-name=letsencrypt-R3.pem passphrase="";
![screenshot: import certs](README.d/02-import-certs.avif) ![screenshot: import certs](README.d/02-import-certs.avif)
For basic verification we rename the certificates and print their count. Make For basic verification we rename the certificates and print their count. Make
sure the certificate count is **two**. sure the certificate count is **two**.
/ certificate set name="R3" [ find where fingerprint="67add1166b020ae61b8f5fc96813c04c2aa589960796865572a3c7e737613dfd" ]; /certificate/set name="R3" [ find where fingerprint="67add1166b020ae61b8f5fc96813c04c2aa589960796865572a3c7e737613dfd" ];
/ certificate set name="ISRG-Root-X1" [ find where fingerprint="96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6" ]; /certificate/set name="ISRG-Root-X1" [ find where fingerprint="96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6" ];
/ certificate print count-only where fingerprint="67add1166b020ae61b8f5fc96813c04c2aa589960796865572a3c7e737613dfd" or fingerprint="96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6"; /certificate/print count-only where fingerprint="67add1166b020ae61b8f5fc96813c04c2aa589960796865572a3c7e737613dfd" or fingerprint="96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6";
![screenshot: check certs](README.d/03-check-certs.avif) ![screenshot: check certs](README.d/03-check-certs.avif)
@ -82,14 +85,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 certificate's lifetime is checked with local time, so make sure the device's
date and time is set correctly! 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. 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) 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 . $ScriptUpdatesUrlSuffix) output=user as-value]->"data"); };
![screenshot: import scripts](README.d/04-import-scripts.avif) ![screenshot: import scripts](README.d/04-import-scripts.avif)
@ -98,35 +96,24 @@ The configuration needs to be tweaked for your needs. Edit
[`global-config`](global-config) (the one without `-overlay`). [`global-config`](global-config) (the one without `-overlay`).
Save changes and exit with `Ctrl-o`. Save changes and exit with `Ctrl-o`.
/ system script edit global-config-overlay source; /system/script edit global-config-overlay source;
![screenshot: edit global-config-overlay](README.d/05-edit-global-config-overlay.avif) ![screenshot: edit global-config-overlay](README.d/05-edit-global-config-overlay.avif)
And finally load configuration and functions and add the scheduler. And finally load configuration and functions and add the scheduler.
/ system script { run global-config; run global-functions; }; /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; }"; /system/scheduler/add name="global-scripts" start-time=startup on-event="/system/script { run global-config; run global-functions; }";
![screenshot: run and schedule scripts](README.d/06-run-and-schedule-scripts.avif) ![screenshot: run and schedule scripts](README.d/06-run-and-schedule-scripts.avif)
The last step is optional: Add this scheduler **only** if you want the scripts The last step is optional: Add this scheduler **only** if you want the scripts
to be updated automatically! to be updated automatically!
/ system scheduler add name="ScriptInstallUpdate" start-time=startup interval=1d on-event=":global ScriptInstallUpdate; \$ScriptInstallUpdate;"; /system/scheduler/add name="ScriptInstallUpdate" start-time=startup interval=1d on-event=":global ScriptInstallUpdate; \$ScriptInstallUpdate;";
![screenshot: schedule update](README.d/07-schedule-update.avif) ![screenshot: schedule update](README.d/07-schedule-update.avif)
### Changes for RouterOS v6
RouterOS v7 is the way to go, let's consider RouterOS v6 deprecated.
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";
Then reload the configuration.
Updating scripts Updating scripts
---------------- ----------------
@ -155,7 +142,7 @@ Most scripts are designed to run regularly from
added `check-routeros-update`, so let's run it every hour to make sure not to added `check-routeros-update`, so let's run it every hour to make sure not to
miss an update. miss an update.
/ system scheduler add name="check-routeros-update" interval=1h on-event="/ system script run check-routeros-update;"; /system/scheduler/add name="check-routeros-update" interval=1h on-event="/system/script/run check-routeros-update;";
![screenshot: schedule script](README.d/10-schedule-script.avif) ![screenshot: schedule script](README.d/10-schedule-script.avif)
@ -164,8 +151,8 @@ in DNS use `dhcp-to-dns` with the events from dhcp server. For a regular
cleanup add a scheduler entry. cleanup add a scheduler entry.
$ScriptInstallUpdate dhcp-to-dns,lease-script; $ScriptInstallUpdate dhcp-to-dns,lease-script;
/ ip dhcp-server set lease-script=lease-script [ find ]; /ip/dhcp-server/set lease-script=lease-script [ find ];
/ system scheduler add name="dhcp-to-dns" interval=5m on-event="/ system script run dhcp-to-dns;"; /system/scheduler/add name="dhcp-to-dns" interval=5m on-event="/system/script/run dhcp-to-dns;";
![screenshot: setup lease script](README.d/11-setup-lease-script.avif) ![screenshot: setup lease script](README.d/11-setup-lease-script.avif)
@ -240,7 +227,7 @@ still use my scripts to manage and deploy yours, by specifying `base-url`
This will fetch and install a script `hello-world.rsc` from the given url: 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/" $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) ![screenshot: install custom script](README.d/12-install-custom-script.avif)

View file

@ -17,8 +17,8 @@
:local Seen [ :toarray "" ]; :local Seen [ :toarray "" ];
:local Shown [ :toarray "" ]; :local Shown [ :toarray "" ];
:foreach AccList in=[ / caps-man access-list find where mac-address!="00:00:00:00:00:00" ] do={ :foreach AccList in=[ /caps-man/access-list/find where mac-address!="00:00:00:00:00:00" ] do={
:local Mac [ / caps-man access-list get $AccList mac-address ]; :local Mac [ /caps-man/access-list/get $AccList mac-address ];
:foreach SeenMac in=$Seen do={ :foreach SeenMac in=$Seen do={
:if ($SeenMac = $Mac) do={ :if ($SeenMac = $Mac) do={
:local Skip 0; :local Skip 0;
@ -26,14 +26,14 @@
:if ($ShownMac = $Mac) do={ :set Skip 1; } :if ($ShownMac = $Mac) do={ :set Skip 1; }
} }
:if ($Skip = 0) do={ :if ($Skip = 0) do={
/ caps-man access-list print where mac-address=$Mac; /caps-man/access-list/print where mac-address=$Mac;
:set Shown ($Shown, $Mac); :set Shown ($Shown, $Mac);
:put "\nNumeric id to remove, any key to skip!"; :put "\nNumeric id to remove, any key to skip!";
:local Remove [ :tonum [ $Read ] ]; :local Remove [ :tonum [ $Read ] ];
:if ([ :typeof $Remove ] = "num") do={ :if ([ :typeof $Remove ] = "num") do={
:put ("Removing numeric id " . $Remove . "...\n"); :put ("Removing numeric id " . $Remove . "...\n");
/ caps-man access-list remove $Remove; /caps-man/access-list/remove $Remove;
} }
} }
} }

View file

@ -17,8 +17,8 @@
:local Seen [ :toarray "" ]; :local Seen [ :toarray "" ];
:local Shown [ :toarray "" ]; :local Shown [ :toarray "" ];
:foreach AccList in=[ / interface wireless access-list find where mac-address!="00:00:00:00:00:00" ] do={ :foreach AccList in=[ /interface/wireless/access-list/find where mac-address!="00:00:00:00:00:00" ] do={
:local Mac [ / interface wireless access-list get $AccList mac-address ]; :local Mac [ /interface/wireless/access-list/get $AccList mac-address ];
:foreach SeenMac in=$Seen do={ :foreach SeenMac in=$Seen do={
:if ($SeenMac = $Mac) do={ :if ($SeenMac = $Mac) do={
:local Skip 0; :local Skip 0;
@ -26,14 +26,14 @@
:if ($ShownMac = $Mac) do={ :set Skip 1; } :if ($ShownMac = $Mac) do={ :set Skip 1; }
} }
:if ($Skip = 0) do={ :if ($Skip = 0) do={
/ interface wireless access-list print where mac-address=$Mac; /interface/wireless/access-list/print where mac-address=$Mac;
:set Shown ($Shown, $Mac); :set Shown ($Shown, $Mac);
:put "\nNumeric id to remove, any key to skip!"; :put "\nNumeric id to remove, any key to skip!";
:local Remove [ :tonum [ $Read ] ]; :local Remove [ :tonum [ $Read ] ];
:if ([ :typeof $Remove ] = "num") do={ :if ([ :typeof $Remove ] = "num") do={
:put ("Removing numeric id " . $Remove . "...\n"); :put ("Removing numeric id " . $Remove . "...\n");
/ interface wireless access-list remove $Remove; /interface/wireless/access-list/remove $Remove;
} }
} }
} }

View file

@ -18,8 +18,8 @@
:local Seen [ :toarray "" ]; :local Seen [ :toarray "" ];
:local Shown [ :toarray "" ]; :local Shown [ :toarray "" ];
:foreach AccList in=[ / %PATH% access-list find where mac-address!="00:00:00:00:00:00" ] do={ :foreach AccList in=[ /%PATH%/access-list/find where mac-address!="00:00:00:00:00:00" ] do={
:local Mac [ / %PATH% access-list get $AccList mac-address ]; :local Mac [ /%PATH%/access-list/get $AccList mac-address ];
:foreach SeenMac in=$Seen do={ :foreach SeenMac in=$Seen do={
:if ($SeenMac = $Mac) do={ :if ($SeenMac = $Mac) do={
:local Skip 0; :local Skip 0;
@ -27,14 +27,14 @@
:if ($ShownMac = $Mac) do={ :set Skip 1; } :if ($ShownMac = $Mac) do={ :set Skip 1; }
} }
:if ($Skip = 0) do={ :if ($Skip = 0) do={
/ %PATH% access-list print where mac-address=$Mac; /%PATH%/access-list/print where mac-address=$Mac;
:set Shown ($Shown, $Mac); :set Shown ($Shown, $Mac);
:put "\nNumeric id to remove, any key to skip!"; :put "\nNumeric id to remove, any key to skip!";
:local Remove [ :tonum [ $Read ] ]; :local Remove [ :tonum [ $Read ] ];
:if ([ :typeof $Remove ] = "num") do={ :if ([ :typeof $Remove ] = "num") do={
:put ("Removing numeric id " . $Remove . "...\n"); :put ("Removing numeric id " . $Remove . "...\n");
/ %PATH% access-list remove $Remove; /%PATH%/access-list/remove $Remove;
} }
} }
} }

View file

@ -33,15 +33,15 @@ $WaitFullyConnected;
:do { :do {
# we are not interested in output, but print is # we are not interested in output, but print is
# required to fetch information from cloud # required to fetch information from cloud
/ system backup cloud print as-value; /system/backup/cloud/print as-value;
:if ([ :len [ / system backup cloud find ] ] > 0) do={ :if ([ :len [ /system/backup/cloud/find ] ] > 0) do={
/ system backup cloud upload-file action=create-and-upload \ /system/backup/cloud/upload-file action=create-and-upload \
password=$BackupPassword replace=[ get ([ find ]->0) name ]; password=$BackupPassword replace=[ get ([ find ]->0) name ];
} else={ } else={
/ system backup cloud upload-file action=create-and-upload \ /system/backup/cloud/upload-file action=create-and-upload \
password=$BackupPassword; password=$BackupPassword;
} }
:local Cloud [ / system backup cloud get ([ find ]->0) ]; :local Cloud [ /system/backup/cloud/get ([ find ]->0) ];
$SendNotification2 ({ origin=$0; \ $SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "floppy-disk,cloud" ] . "Cloud backup"); \ subject=([ $SymbolForNotification "floppy-disk,cloud" ] . "Cloud backup"); \

View file

@ -54,7 +54,7 @@ $WaitFullyConnected;
# binary backup # binary backup
:if ($BackupSendBinary = true) do={ :if ($BackupSendBinary = true) do={
/ system backup save encryption=aes-sha256 name=$FilePath password=$BackupPassword; /system/backup/save encryption=aes-sha256 name=$FilePath password=$BackupPassword;
$WaitForFile ($FilePath . ".backup"); $WaitForFile ($FilePath . ".backup");
:set BackupFile ($FileName . ".backup"); :set BackupFile ($FileName . ".backup");
:set Attach ($Attach, ($FilePath . ".backup")); :set Attach ($Attach, ($FilePath . ".backup"));
@ -62,7 +62,7 @@ $WaitFullyConnected;
# create configuration export # create configuration export
:if ($BackupSendExport = true) do={ :if ($BackupSendExport = true) do={
/ export terse show-sensitive file=$FilePath; /export terse show-sensitive file=$FilePath;
$WaitForFile ($FilePath . ".rsc"); $WaitForFile ($FilePath . ".rsc");
:set ConfigFile ($FileName . ".rsc"); :set ConfigFile ($FileName . ".rsc");
:set Attach ($Attach, ($FilePath . ".rsc")); :set Attach ($Attach, ($FilePath . ".rsc"));

View file

@ -14,20 +14,20 @@
:global LogPrintExit2; :global LogPrintExit2;
:if ([ :len [ / partitions find ] ] < 2) do={ :if ([ :len [ /partitions/find ] ] < 2) do={
$LogPrintExit2 error $0 ("Device does not have a fallback partition.") true; $LogPrintExit2 error $0 ("Device does not have a fallback partition.") true;
} }
:local ActiveRunning [ / partitions find where active running ]; :local ActiveRunning [ /partitions/find where active running ];
:if ([ :len $ActiveRunning ] < 1) do={ :if ([ :len $ActiveRunning ] < 1) do={
$LogPrintExit2 error $0 ("Device is not running from active partition.") true; $LogPrintExit2 error $0 ("Device is not running from active partition.") true;
} }
:local ActiveRunningVar [ / partitions get $ActiveRunning ]; :local ActiveRunningVar [ /partitions/get $ActiveRunning ];
:do { :do {
/ partitions save-config-to ($ActiveRunningVar->"fallback-to"); /partitions/save-config-to ($ActiveRunningVar->"fallback-to");
$LogPrintExit2 info $0 ("Saved configuration to partition '" . \ $LogPrintExit2 info $0 ("Saved configuration to partition '" . \
($ActiveRunningVar->"fallback-to") . "'.") false; ($ActiveRunningVar->"fallback-to") . "'.") false;
} on-error={ } on-error={

View file

@ -58,11 +58,11 @@ $WaitFullyConnected;
# binary backup # binary backup
:if ($BackupSendBinary = true) do={ :if ($BackupSendBinary = true) do={
/ system backup save encryption=aes-sha256 name=$FilePath password=$BackupPassword; /system/backup/save encryption=aes-sha256 name=$FilePath password=$BackupPassword;
$WaitForFile ($FilePath . ".backup"); $WaitForFile ($FilePath . ".backup");
:do { :do {
/ tool fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".backup") \ /tool/fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".backup") \
user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".backup"); user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".backup");
:set BackupFile ($FileName . ".backup"); :set BackupFile ($FileName . ".backup");
} on-error={ } on-error={
@ -71,16 +71,16 @@ $WaitFullyConnected;
:set Failed 1; :set Failed 1;
} }
/ file remove ($FilePath . ".backup"); /file/remove ($FilePath . ".backup");
} }
# create configuration export # create configuration export
:if ($BackupSendExport = true) do={ :if ($BackupSendExport = true) do={
/ export terse show-sensitive file=$FilePath; /export terse show-sensitive file=$FilePath;
$WaitForFile ($FilePath . ".rsc"); $WaitForFile ($FilePath . ".rsc");
:do { :do {
/ tool fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".rsc") \ /tool/fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".rsc") \
user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".rsc"); user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".rsc");
:set ConfigFile ($FileName . ".rsc"); :set ConfigFile ($FileName . ".rsc");
} on-error={ } on-error={
@ -89,7 +89,7 @@ $WaitFullyConnected;
:set Failed 1; :set Failed 1;
} }
/ file remove ($FilePath . ".rsc"); /file/remove ($FilePath . ".rsc");
} }
$SendNotification2 ({ origin=$0; \ $SendNotification2 ({ origin=$0; \

View file

@ -21,15 +21,15 @@
$ScriptLock $0; $ScriptLock $0;
$WaitFullyConnected; $WaitFullyConnected;
:local PackagePath [ $CleanFilePath [ / caps-man manager get package-path ] ]; :local PackagePath [ $CleanFilePath [ /caps-man/manager/get package-path ] ];
:local InstalledVersion [ / system package update get installed-version ]; :local InstalledVersion [ /system/package/update/get installed-version ];
:local Updated false; :local Updated false;
:if ([ :len $PackagePath ] = 0) do={ :if ([ :len $PackagePath ] = 0) do={
$LogPrintExit2 warning $0 ("The CAPsMAN package path is not defined, can not download packages.") true; $LogPrintExit2 warning $0 ("The CAPsMAN package path is not defined, can not download packages.") true;
} }
:if ([ :len [ / file find where name=$PackagePath type="directory" ] ] = 0) do={ :if ([ :len [ /file/find where name=$PackagePath type="directory" ] ] = 0) do={
:if ([ $MkDir $PackagePath ] = false) do={ :if ([ $MkDir $PackagePath ] = false) do={
$LogPrintExit2 warning $0 ("Creating directory at CAPsMAN package path (" . \ $LogPrintExit2 warning $0 ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!") true; $PackagePath . ") failed!") true;
@ -38,34 +38,34 @@ $WaitFullyConnected;
"). Please place your packages!") false; "). Please place your packages!") false;
} }
:foreach Package in=[ / file find where type=package \ :foreach Package in=[ /file/find where type=package \
package-version!=$InstalledVersion name~("^" . $PackagePath) ] do={ package-version!=$InstalledVersion name~("^" . $PackagePath) ] do={
:local File [ / file get $Package ]; :local File [ /file/get $Package ];
:if ($File->"package-architecture" = "mips") do={ :if ($File->"package-architecture" = "mips") do={
:set ($File->"package-architecture") "mipsbe"; :set ($File->"package-architecture") "mipsbe";
} }
:if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \ :if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \
($File->"package-architecture") $PackagePath ] = true) do={ ($File->"package-architecture") $PackagePath ] = true) do={
:set Updated true; :set Updated true;
/ file remove $Package; /file/remove $Package;
} }
} }
:if ([ :len [ / system logging find where topics~"error" !(topics~"!error") \ :if ([ :len [ /system/logging/find where topics~"error" !(topics~"!error") \
!(topics~"!caps") action=memory !disabled !invalid ] ] < 1) do={ !(topics~"!caps") action=memory !disabled !invalid ] ] < 1) do={
$LogPrintExit2 warning $0 ("Looks like error messages for 'caps' are not sent to memory. " . \ $LogPrintExit2 warning $0 ("Looks like error messages for 'caps' are not sent to memory. " . \
"Probably can not download packages automatically.") false; "Probably can not download packages automatically.") false;
} else={ } else={
:if ($Updated = false && [ / system resource get uptime ] < 2m) do={ :if ($Updated = false && [ /system/resource/get uptime ] < 2m) do={
$LogPrintExit2 info $0 ("No packages downloaded, yet. Delaying for logs.") false; $LogPrintExit2 info $0 ("No packages downloaded, yet. Delaying for logs.") false;
:delay 2m; :delay 2m;
} }
} }
:foreach Log in=[ / log find where topics=({"caps", "error"}) \ :foreach Log in=[ /log/find where topics=({"caps", "error"}) \
message~("upgrade status: failed, failed to download file '.*-" . $InstalledVersion . \ message~("upgrade status: failed, failed to download file '.*-" . $InstalledVersion . \
"-.*\\.npk', no such file") ] do={ "-.*\\.npk', no such file") ] do={
:local Message [ / log get $Log message ]; :local Message [ /log/get $Log message ];
:local Package [ :pick $Message \ :local Package [ :pick $Message \
([ :find $Message "'" ] + 1) \ ([ :find $Message "'" ] + 1) \
[ :find $Message ("-" . $InstalledVersion . "-") ] ]; [ :find $Message ("-" . $InstalledVersion . "-") ] ];
@ -78,9 +78,9 @@ $WaitFullyConnected;
} }
:if ($Updated = true) do={ :if ($Updated = true) do={
:if ([ :len [ / system script find where name="capsman-rolling-upgrade" ] ] > 0) do={ :if ([ :len [ /system/script/find where name="capsman-rolling-upgrade" ] ] > 0) do={
/ system script run capsman-rolling-upgrade; /system/script/run capsman-rolling-upgrade;
} else={ } else={
/ caps-man remote-cap upgrade [ find where version!=$InstalledVersion ]; /caps-man/remote-cap/upgrade [ find where version!=$InstalledVersion ];
} }
} }

View file

@ -16,18 +16,18 @@
$ScriptLock $0; $ScriptLock $0;
:local InstalledVersion [ / system package update get installed-version ]; :local InstalledVersion [ /system/package/update/get installed-version ];
:local RemoteCapCount [ :len [ / caps-man remote-cap find ] ]; :local RemoteCapCount [ :len [ /caps-man/remote-cap/find ] ];
:if ($RemoteCapCount > 0) do={ :if ($RemoteCapCount > 0) do={
:local Delay (600 / $RemoteCapCount); :local Delay (600 / $RemoteCapCount);
:if ($Delay > 120) do={ :set Delay 120; } :if ($Delay > 120) do={ :set Delay 120; }
:foreach RemoteCap in=[ / caps-man remote-cap find where version!=$InstalledVersion ] do={ :foreach RemoteCap in=[ /caps-man/remote-cap/find where version!=$InstalledVersion ] do={
:local RemoteCapVal [ / caps-man remote-cap get $RemoteCap ]; :local RemoteCapVal [ /caps-man/remote-cap/get $RemoteCap ];
:if ([ :len $RemoteCapVal ] > 1) do={ :if ([ :len $RemoteCapVal ] > 1) do={
$LogPrintExit2 info $0 ("Starting upgrade for " . $RemoteCapVal->"name" . \ $LogPrintExit2 info $0 ("Starting upgrade for " . $RemoteCapVal->"name" . \
" (" . $RemoteCapVal->"identity" . ")...") false; " (" . $RemoteCapVal->"identity" . ")...") false;
/ caps-man remote-cap upgrade $RemoteCap; /caps-man/remote-cap/upgrade $RemoteCap;
} else={ } else={
$LogPrintExit2 warning $0 ("Remote CAP vanished, skipping upgrade.") false; $LogPrintExit2 warning $0 ("Remote CAP vanished, skipping upgrade.") false;
} }

View file

@ -15,16 +15,16 @@
:global LogPrintExit2; :global LogPrintExit2;
:global MkDir; :global MkDir;
:foreach Cert in=[ / certificate find where issued expires-after<3w ] do={ :foreach Cert in=[ /certificate/find where issued expires-after<3w ] do={
:local CertVal [ / certificate get $Cert ]; :local CertVal [ /certificate/get $Cert ];
/ certificate issued-revoke $Cert; /certificate/issued-revoke $Cert;
/ certificate set name=($CertVal->"name" . "-revoked-" . [ / system clock get date ]) $Cert; /certificate/set name=($CertVal->"name" . "-revoked-" . [ /system/clock/get date ]) $Cert;
/ certificate add name=($CertVal->"name") common-name=($CertVal->"common-name") \ /certificate/add name=($CertVal->"name") common-name=($CertVal->"common-name") \
key-usage=($CertVal->"key-usage") subject-alt-name=($CertVal->"subject-alt-name"); key-usage=($CertVal->"key-usage") subject-alt-name=($CertVal->"subject-alt-name");
/ certificate sign ($CertVal->"name") ca=($CertVal->"ca"); /certificate/sign ($CertVal->"name") ca=($CertVal->"ca");
:if ([ :typeof ($CertIssuedExportPass->($CertVal->"common-name")) ] = "str") do={ :if ([ :typeof ($CertIssuedExportPass->($CertVal->"common-name")) ] = "str") do={
:if ([ $MkDir "cert-issued" ] = true) do={ :if ([ $MkDir "cert-issued" ] = true) do={
/ certificate export-certificate ($CertVal->"name") type=pkcs12 \ /certificate/export-certificate ($CertVal->"name") type=pkcs12 \
file-name=("cert-issued/" . $CertVal->"common-name") \ file-name=("cert-issued/" . $CertVal->"common-name") \
export-passphrase=($CertIssuedExportPass->($CertVal->"common-name")); export-passphrase=($CertIssuedExportPass->($CertVal->"common-name"));
$LogPrintExit2 info $0 ("Issued a new certificate for \"" . $CertVal->"common-name" . \ $LogPrintExit2 info $0 ("Issued a new certificate for \"" . $CertVal->"common-name" . \

View file

@ -33,8 +33,8 @@
$WaitFullyConnected; $WaitFullyConnected;
:foreach Cert in=[ / certificate find where !revoked !ca !scep-url expires-after<$CertRenewTime ] do={ :foreach Cert in=[ /certificate/find where !revoked !ca !scep-url expires-after<$CertRenewTime ] do={
:local CertVal [ / certificate get $Cert ]; :local CertVal [ /certificate/get $Cert ];
:do { :do {
:if ([ :len $CertRenewUrl ] = 0) do={ :if ([ :len $CertRenewUrl ] = 0) do={
@ -45,24 +45,24 @@ $WaitFullyConnected;
:foreach Type in={ ".pem"; ".p12" } do={ :foreach Type in={ ".pem"; ".p12" } do={
:local CertFileName ([ $UrlEncode ($CertVal->"common-name") ] . $Type); :local CertFileName ([ $UrlEncode ($CertVal->"common-name") ] . $Type);
:do { :do {
/ tool fetch check-certificate=yes-without-crl \ /tool/fetch check-certificate=yes-without-crl \
($CertRenewUrl . $CertFileName) dst-path=$CertFileName as-value; ($CertRenewUrl . $CertFileName) dst-path=$CertFileName as-value;
$WaitForFile $CertFileName; $WaitForFile $CertFileName;
:foreach PassPhrase in=$CertRenewPass do={ :foreach PassPhrase in=$CertRenewPass do={
/ certificate import file-name=$CertFileName passphrase=$PassPhrase as-value; /certificate/import file-name=$CertFileName passphrase=$PassPhrase as-value;
} }
/ file remove [ find where name=$CertFileName ]; /file/remove [ find where name=$CertFileName ];
:foreach CertInChain in=[ / certificate find where name~("^" . $CertFileName . "_[0-9]+\$") common-name!=($CertVal->"common-name") ] do={ :foreach CertInChain in=[ /certificate/find where name~("^" . $CertFileName . "_[0-9]+\$") common-name!=($CertVal->"common-name") ] do={
$CertificateNameByCN [ / certificate get $CertInChain common-name ]; $CertificateNameByCN [ /certificate/get $CertInChain common-name ];
} }
} on-error={ } on-error={
$LogPrintExit2 debug $0 ("Could not download certificate file " . $CertFileName) false; $LogPrintExit2 debug $0 ("Could not download certificate file " . $CertFileName) false;
} }
} }
:local CertNew [ / certificate find where common-name=($CertVal->"common-name") fingerprint!=[ :tostr ($CertVal->"fingerprint") ] expires-after>$CertRenewTime ]; :local CertNew [ /certificate/find where common-name=($CertVal->"common-name") fingerprint!=[ :tostr ($CertVal->"fingerprint") ] expires-after>$CertRenewTime ];
:local CertNewVal [ / certificate get $CertNew ]; :local CertNewVal [ /certificate/get $CertNew ];
:if ([ $CertificateAvailable ([ $ParseKeyValueStore ($CertNewVal->"issuer") ]->"CN") ] = false) do={ :if ([ $CertificateAvailable ([ $ParseKeyValueStore ($CertNewVal->"issuer") ]->"CN") ] = false) do={
$LogPrintExit2 warning $0 ("The certificate chain is not available!") false; $LogPrintExit2 warning $0 ("The certificate chain is not available!") false;
@ -72,27 +72,19 @@ $WaitFullyConnected;
$LogPrintExit2 debug $0 ("Certificate '" . $CertVal->"name" . "' was not updated, but replaced.") false; $LogPrintExit2 debug $0 ("Certificate '" . $CertVal->"name" . "' was not updated, but replaced.") false;
:if (($CertVal->"private-key") = true && ($CertVal->"private-key") != ($CertNewVal->"private-key")) do={ :if (($CertVal->"private-key") = true && ($CertVal->"private-key") != ($CertNewVal->"private-key")) do={
/ certificate remove $CertNew; /certificate/remove $CertNew;
$LogPrintExit2 warning $0 ("Old certificate '" . ($CertVal->"name") . "' has a private key, new certificate does not. Aborting renew.") true; $LogPrintExit2 warning $0 ("Old certificate '" . ($CertVal->"name") . "' has a private key, new certificate does not. Aborting renew.") true;
} }
/ ip service set certificate=($CertNewVal->"name") [ find where certificate=($CertVal->"name") ]; /ip/service/set certificate=($CertNewVal->"name") [ find where certificate=($CertVal->"name") ];
:do { /ip/ipsec/identity/set certificate=($CertNewVal->"name") [ find where certificate=($CertVal->"name") ];
/ ip ipsec identity set certificate=($CertNewVal->"name") [ / ip ipsec identity find where certificate=($CertVal->"name") ]; /ip/ipsec/identity/set remote-certificate=($CertNewVal->"name") [ find where remote-certificate=($CertVal->"name") ];
/ ip ipsec identity set remote-certificate=($CertNewVal->"name") [ / ip ipsec identity find where remote-certificate=($CertVal->"name") ];
} on-error={
$LogPrintExit2 debug $0 ("Setting IPSEC certificates failed. Package 'security' not installed?") false;
}
:do { /ip/hotspot/profile/set ssl-certificate=($CertNewVal->"name") [ find where ssl-certificate=($CertVal->"name") ];
/ ip hotspot profile set ssl-certificate=($CertNewVal->"name") [ / ip hotspot profile find where ssl-certificate=($CertVal->"name") ];
} on-error={
$LogPrintExit2 debug $0 ("Setting hotspot certificates failed. Package 'hotspot' not installed?") false;
}
/ certificate remove $Cert; /certificate/remove $Cert;
/ certificate set $CertNew name=($CertVal->"name"); /certificate/set $CertNew name=($CertVal->"name");
} }
$SendNotification2 ({ origin=$0; \ $SendNotification2 ({ origin=$0; \
@ -111,10 +103,10 @@ $WaitFullyConnected;
} }
} }
:foreach Cert in=[ / certificate find where !revoked !scep-url !(expires-after=[]) expires-after<2w !(fingerprint=[]) ] do={ :foreach Cert in=[ /certificate/find where !revoked !scep-url !(expires-after=[]) expires-after<2w !(fingerprint=[]) ] do={
:local CertVal [ / certificate get $Cert ]; :local CertVal [ /certificate/get $Cert ];
:if ([ :len [ / certificate scep-server find where ca-cert=($CertVal->"ca") ] ] > 0) do={ :if ([ :len [ /certificate/scep-server/find where ca-cert=($CertVal->"ca") ] ] > 0) do={
$LogPrintExit2 debug $0 ("Certificate \"" . ($CertVal->"name") . "\" is handled by SCEP, skipping.") false; $LogPrintExit2 debug $0 ("Certificate \"" . ($CertVal->"name") . "\" is handled by SCEP, skipping.") false;
} else={ } else={
:local State [ $IfThenElse (($CertVal->"expired") = true) "expired" "is about to expire" ]; :local State [ $IfThenElse (($CertVal->"expired") = true) "expired" "is about to expire" ];

View file

@ -30,7 +30,7 @@
:return ($T->0 * 10 + $T->1); :return ($T->0 * 10 + $T->1);
} }
:if ([ :len [ / system health find ] ] = 0) do={ :if ([ :len [ /system/health/find ] ] = 0) do={
$LogPrintExit2 error $0 ("Your device does not provide any health values.") true; $LogPrintExit2 error $0 ("Your device does not provide any health values.") true;
} }
@ -43,9 +43,9 @@
$ScriptLock $0; $ScriptLock $0;
:foreach Voltage in=[ / system health find where type="V" ] do={ :foreach Voltage in=[ /system/health/find where type="V" ] do={
:local Name [ / system health get $Voltage name ]; :local Name [ /system/health/get $Voltage name ];
:local Value [ / system health get $Voltage value ]; :local Value [ /system/health/get $Voltage value ];
:if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={ :if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={
:local NumCurr [ $TempToNum $Value ]; :local NumCurr [ $TempToNum $Value ];
@ -75,9 +75,9 @@ $ScriptLock $0;
:set ($CheckHealthLast->$Name) $Value; :set ($CheckHealthLast->$Name) $Value;
} }
:foreach PSU in=[ / system health find where name~"^psu.*-state\$" ] do={ :foreach PSU in=[ /system/health/find where name~"^psu.*-state\$" ] do={
:local Name [ / system health get $PSU name ]; :local Name [ /system/health/get $PSU name ];
:local Value [ / system health get $PSU value ]; :local Value [ /system/health/get $PSU value ];
:if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={ :if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={
:if ($CheckHealthLast->$Name = "ok" && \ :if ($CheckHealthLast->$Name = "ok" && \
@ -96,19 +96,19 @@ $ScriptLock $0;
:set ($CheckHealthLast->$Name) $Value; :set ($CheckHealthLast->$Name) $Value;
} }
:foreach Temperature in=[ / system health find where type="C" ] do={ :foreach Temperature in=[ /system/health/find where type="C" ] do={
:local Name [ / system health get $Temperature name ]; :local Name [ /system/health/get $Temperature name ];
:local Value [ / system health get $Temperature value ]; :local Value [ /system/health/get $Temperature value ];
:if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={ :if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={
:if ([ :typeof ($CheckHealthTemperature->$Name) ] != "num" ) do={ :if ([ :typeof ($CheckHealthTemperature->$Name) ] != "num" ) do={
$LogPrintExit2 info $0 ("No threshold given for " . $Name . ", assuming 50C.") false; $LogPrintExit2 info $0 ("No threshold given for " . $Name . ", assuming 50C.") false;
:set ($CheckHealthTemperature->$Name) 50; :set ($CheckHealthTemperature->$Name) 50;
} }
:local Validate [ / system health get [ find where name=$Name ] value ]; :local Validate [ /system/health/get [ find where name=$Name ] value ];
:while ($Value != $Validate) do={ :while ($Value != $Validate) do={
:set Value $Validate; :set Value $Validate;
:set Validate [ / system health get [ find where name=$Name ] value ]; :set Validate [ /system/health/get [ find where name=$Name ] value ];
} }
:if ($Value > $CheckHealthTemperature->$Name && \ :if ($Value > $CheckHealthTemperature->$Name && \
$CheckHealthTemperatureNotified->$Name != true) do={ $CheckHealthTemperatureNotified->$Name != true) do={

View file

@ -28,12 +28,12 @@
:global SendNotification2; :global SendNotification2;
:global SymbolForNotification; :global SymbolForNotification;
:local IntName [ / interface lte get $Interface name ]; :local IntName [ /interface/lte/get $Interface name ];
:local Firmware; :local Firmware;
:local Info; :local Info;
:do { :do {
:set Firmware [ / interface lte firmware-upgrade $Interface once as-value ]; :set Firmware [ /interface/lte/firmware-upgrade $Interface once as-value ];
:set Info [ / interface lte monitor $Interface once as-value ]; :set Info [ /interface/lte/monitor $Interface once as-value ];
} on-error={ } on-error={
$LogPrintExit2 debug $0 ("Could not get latest LTE firmware version for interface " . \ $LogPrintExit2 debug $0 ("Could not get latest LTE firmware version for interface " . \
$IntName . ".") false; $IntName . ".") false;
@ -48,10 +48,10 @@
} }
:if ([ $ScriptFromTerminal "check-lte-firmware-upgrade" ] = true && \ :if ([ $ScriptFromTerminal "check-lte-firmware-upgrade" ] = true && \
[ :len [ / system script find where name="unattended-lte-firmware-upgrade" ] ] > 0) do={ [ :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]"); :put ("Do you want to start unattended lte firmware upgrade for interface " . $IntName . "? [y/N]");
:if (([ / terminal inkey timeout=60 ] % 32) = 25) do={ :if (([ /terminal/inkey timeout=60 ] % 32) = 25) do={
/ system script run unattended-lte-firmware-upgrade; /system/script/run unattended-lte-firmware-upgrade;
$LogPrintExit2 info $0 ("Scheduled lte firmware upgrade for interface " . $IntName . "...") false; $LogPrintExit2 info $0 ("Scheduled lte firmware upgrade for interface " . $IntName . "...") false;
:return true; :return true;
} else={ } else={
@ -77,6 +77,6 @@
:set ($SentLteFirmwareUpgradeNotification->$IntName) ($Firmware->"latest"); :set ($SentLteFirmwareUpgradeNotification->$IntName) ($Firmware->"latest");
} }
:foreach Interface in=[ / interface lte find ] do={ :foreach Interface in=[ /interface/lte/find ] do={
$CheckInterface $Interface; $CheckInterface $Interface;
} }

View file

@ -27,10 +27,10 @@
:global WaitFullyConnected; :global WaitFullyConnected;
:local DoUpdate do={ :local DoUpdate do={
:if ([ :len [ / system script find where name="packages-update" ] ] > 0) do={ :if ([ :len [ /system/script/find where name="packages-update" ] ] > 0) do={
/ system script run packages-update; /system/script/run packages-update;
} else={ } else={
/ system package update install without-paging; /system/package/update/install without-paging;
} }
:error "Waiting for system to reboot."; :error "Waiting for system to reboot.";
} }
@ -39,21 +39,21 @@ $ScriptLock $0;
$WaitFullyConnected; $WaitFullyConnected;
:if ([ :len [ / system package find where name="wireless" disabled=no ] ] > 0) do={ :if ([ :len [ /system/package/find where name="wireless" disabled=no ] ] > 0) do={
:if ([ / interface wireless cap get enabled ] = true && \ :if ([ /interface/wireless/cap/get enabled ] = true && \
[ / caps-man manager get enabled ] = false && \ [ /caps-man/manager/get enabled ] = false && \
$SafeUpdateOnCap != true) do={ $SafeUpdateOnCap != true) do={
$LogPrintExit2 error $0 ("System is managed by CAPsMAN, not checking for RouterOS version.") true; $LogPrintExit2 error $0 ("System is managed by CAPsMAN, not checking for RouterOS version.") true;
} }
} }
:if ([ :len [ / system scheduler find where name="reboot-for-update" ] ] > 0) do={ :if ([ :len [ /system/scheduler/find where name="reboot-for-update" ] ] > 0) do={
:error "A reboot for update is already scheduled."; :error "A reboot for update is already scheduled.";
} }
$LogPrintExit2 debug $0 ("Checking for updates...") false; $LogPrintExit2 debug $0 ("Checking for updates...") false;
/ system package update check-for-updates without-paging as-value; /system/package/update/check-for-updates without-paging as-value;
:local Update [ / system package update get ]; :local Update [ /system/package/update/get ];
:if ([ :len ($Update->"latest-version") ] = 0) do={ :if ([ :len ($Update->"latest-version") ] = 0) do={
$LogPrintExit2 info $0 ("An empty string is not a valid version.") true; $LogPrintExit2 info $0 ("An empty string is not a valid version.") true;
@ -77,7 +77,7 @@ $LogPrintExit2 debug $0 ("Checking for updates...") false;
$DoUpdate; $DoUpdate;
} }
:if ($SafeUpdateNeighbor = true && [ :len [ / ip neighbor find where \ :if ($SafeUpdateNeighbor = true && [ :len [ /ip/neighbor/find where \
version=($Update->"latest-version" . " (" . $Update->"channel" . ")") ] ] > 0) do={ version=($Update->"latest-version" . " (" . $Update->"channel" . ")") ] ] > 0) do={
$LogPrintExit2 info $0 ("Seen a neighbor running version " . $Update->"latest-version" . ", updating...") false; $LogPrintExit2 info $0 ("Seen a neighbor running version " . $Update->"latest-version" . ", updating...") false;
$SendNotification2 ({ origin=$0; \ $SendNotification2 ({ origin=$0; \
@ -90,7 +90,7 @@ $LogPrintExit2 debug $0 ("Checking for updates...") false;
:if ([ :len $SafeUpdateUrl ] > 0) do={ :if ([ :len $SafeUpdateUrl ] > 0) do={
:local Result; :local Result;
:do { :do {
:set Result [ / tool fetch check-certificate=yes-without-crl \ :set Result [ /tool/fetch check-certificate=yes-without-crl \
($SafeUpdateUrl . $Update->"channel" . "?installed=" . $Update->"installed-version" . \ ($SafeUpdateUrl . $Update->"channel" . "?installed=" . $Update->"installed-version" . \
"&latest=" . $Update->"latest-version") output=user as-value ]; "&latest=" . $Update->"latest-version") output=user as-value ];
} on-error={ } on-error={
@ -108,7 +108,7 @@ $LogPrintExit2 debug $0 ("Checking for updates...") false;
:if ([ $ScriptFromTerminal $0 ] = true) do={ :if ([ $ScriptFromTerminal $0 ] = true) do={
:put ("Do you want to install RouterOS version " . $Update->"latest-version" . "? [y/N]"); :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; $DoUpdate;
} else={ } else={
:put "Canceled..."; :put "Canceled...";

View file

@ -25,47 +25,47 @@
$ScriptLock $0 false 10; $ScriptLock $0 false 10;
:if ([ :len [ / caps-man access-list find where comment="--- collected above ---" disabled ] ] = 0) do={ :if ([ :len [ /caps-man/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
/ caps-man access-list add comment="--- collected above ---" disabled=yes; /caps-man/access-list/add comment="--- collected above ---" disabled=yes;
$LogPrintExit2 warning $0 ("Added disabled access-list entry with comment '--- collected above ---'.") false; $LogPrintExit2 warning $0 ("Added disabled access-list entry with comment '--- collected above ---'.") false;
} }
:local PlaceBefore ([ / caps-man access-list find where comment="--- collected above ---" disabled ]->0); :local PlaceBefore ([ /caps-man/access-list/find where comment="--- collected above ---" disabled ]->0);
:foreach Reg in=[ / caps-man registration-table find ] do={ :foreach Reg in=[ /caps-man/registration-table/find ] do={
:local RegVal; :local RegVal;
:do { :do {
:set RegVal [ / caps-man registration-table get $Reg ]; :set RegVal [ /caps-man/registration-table/get $Reg ];
} on-error={ } on-error={
$LogPrintExit2 debug $0 ("Device already gone... Ignoring.") false; $LogPrintExit2 debug $0 ("Device already gone... Ignoring.") false;
} }
:if ([ :len ($RegVal->"mac-address") ] > 0) do={ :if ([ :len ($RegVal->"mac-address") ] > 0) do={
:local AccessList ([ / caps-man access-list find where mac-address=($RegVal->"mac-address") ]->0); :local AccessList ([ /caps-man/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={ :if ([ :len $AccessList ] > 0) do={
$LogPrintExit2 debug $0 ("MAC address " . $RegVal->"mac-address" . " already known: " . \ $LogPrintExit2 debug $0 ("MAC address " . $RegVal->"mac-address" . " already known: " . \
[ / caps-man access-list get $AccessList comment ]) false; [ /caps-man/access-list/get $AccessList comment ]) false;
} }
:if ([ :len $AccessList ] = 0) do={ :if ([ :len $AccessList ] = 0) do={
:local Address "no dhcp lease"; :local Address "no dhcp lease";
:local DnsName "no dhcp lease"; :local DnsName "no dhcp lease";
:local HostName "no dhcp lease"; :local HostName "no dhcp lease";
:local Lease ([ / ip dhcp-server lease find where mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0); :local Lease ([ /ip/dhcp-server/lease/find where mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0);
:if ([ :len $Lease ] > 0) do={ :if ([ :len $Lease ] > 0) do={
:set Address [ / ip dhcp-server lease get $Lease address ]; :set Address [ /ip/dhcp-server/lease/get $Lease address ];
:set HostName [ $EitherOr [ / ip dhcp-server lease get $Lease host-name ] "no hostname" ]; :set HostName [ $EitherOr [ /ip/dhcp-server/lease/get $Lease host-name ] "no hostname" ];
:set DnsName "no dns name"; :set DnsName "no dns name";
:local DnsRec ([ / ip dns static find where address=$Address ]->0); :local DnsRec ([ /ip/dns/static/find where address=$Address ]->0);
:if ([ :len $DnsRec ] > 0) do={ :if ([ :len $DnsRec ] > 0) do={
:set DnsName [ / ip dns static get $DnsRec name ]; :set DnsName [ /ip/dns/static/get $DnsRec name ];
} }
} }
:local DateTime ([ / system clock get date ] . " " . [ / system clock get time ]); :local DateTime ([ /system/clock/get date ] . " " . [ /system/clock/get time ]);
:local Vendor [ $GetMacVendor ($RegVal->"mac-address") ]; :local Vendor [ $GetMacVendor ($RegVal->"mac-address") ];
:local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \ :local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \
"first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface"); "first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface");
$LogPrintExit2 info $0 $Message false; $LogPrintExit2 info $0 $Message false;
/ caps-man access-list add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes; /caps-man/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
$SendNotification2 ({ origin=$0; \ $SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "mobile-phone" ] . $RegVal->"mac-address" . " connected to " . $RegVal->"ssid"); \ subject=([ $SymbolForNotification "mobile-phone" ] . $RegVal->"mac-address" . " connected to " . $RegVal->"ssid"); \
message=("A device with unknown MAC address connected to " . $RegVal->"ssid" . " on " . $Identity . ".\n\n" . \ message=("A device with unknown MAC address connected to " . $RegVal->"ssid" . " on " . $Identity . ".\n\n" . \

View file

@ -25,48 +25,48 @@
$ScriptLock $0 false 10; $ScriptLock $0 false 10;
:if ([ :len [ / interface wireless access-list find where comment="--- collected above ---" disabled ] ] = 0) do={ :if ([ :len [ /interface/wireless/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
/ interface wireless access-list add comment="--- collected above ---" disabled=yes; /interface/wireless/access-list/add comment="--- collected above ---" disabled=yes;
$LogPrintExit2 warning $0 ("Added disabled access-list entry with comment '--- collected above ---'.") false; $LogPrintExit2 warning $0 ("Added disabled access-list entry with comment '--- collected above ---'.") false;
} }
:local PlaceBefore ([ / interface wireless access-list find where comment="--- collected above ---" disabled ]->0); :local PlaceBefore ([ /interface/wireless/access-list/find where comment="--- collected above ---" disabled ]->0);
:foreach Reg in=[ / interface wireless registration-table find ] do={ :foreach Reg in=[ /interface/wireless/registration-table/find ] do={
:local RegVal; :local RegVal;
:do { :do {
:set RegVal [ / interface wireless registration-table get $Reg ]; :set RegVal [ /interface/wireless/registration-table/get $Reg ];
} on-error={ } on-error={
$LogPrintExit2 debug $0 ("Device already gone... Ignoring.") false; $LogPrintExit2 debug $0 ("Device already gone... Ignoring.") false;
} }
:if ([ :len ($RegVal->"mac-address") ] > 0) do={ :if ([ :len ($RegVal->"mac-address") ] > 0) do={
:local AccessList ([ / interface wireless access-list find where mac-address=($RegVal->"mac-address") ]->0); :local AccessList ([ /interface/wireless/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={ :if ([ :len $AccessList ] > 0) do={
$LogPrintExit2 debug $0 ("MAC address " . $RegVal->"mac-address" . " already known: " . \ $LogPrintExit2 debug $0 ("MAC address " . $RegVal->"mac-address" . " already known: " . \
[ / interface wireless access-list get $AccessList comment ]) false; [ /interface/wireless/access-list/get $AccessList comment ]) false;
} }
:if ([ :len $AccessList ] = 0) do={ :if ([ :len $AccessList ] = 0) do={
:local Address "no dhcp lease"; :local Address "no dhcp lease";
:local DnsName "no dhcp lease"; :local DnsName "no dhcp lease";
:local HostName "no dhcp lease"; :local HostName "no dhcp lease";
:local Lease ([ / ip dhcp-server lease find where mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0); :local Lease ([ /ip/dhcp-server/lease/find where mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0);
:if ([ :len $Lease ] > 0) do={ :if ([ :len $Lease ] > 0) do={
:set Address [ / ip dhcp-server lease get $Lease address ]; :set Address [ /ip/dhcp-server/lease/get $Lease address ];
:set HostName [ $EitherOr [ / ip dhcp-server lease get $Lease host-name ] "no hostname" ]; :set HostName [ $EitherOr [ /ip/dhcp-server/lease/get $Lease host-name ] "no hostname" ];
:set DnsName "no dns name"; :set DnsName "no dns name";
:local DnsRec ([ / ip dns static find where address=$Address ]->0); :local DnsRec ([ /ip/dns/static/find where address=$Address ]->0);
:if ([ :len $DnsRec ] > 0) do={ :if ([ :len $DnsRec ] > 0) do={
:set DnsName [ / ip dns static get $DnsRec name ]; :set DnsName [ /ip/dns/static/get $DnsRec name ];
} }
} }
:set ($RegVal->"ssid") [ / interface wireless get [ find where name=($RegVal->"interface") ] ssid ]; :set ($RegVal->"ssid") [ /interface/wireless/get [ find where name=($RegVal->"interface") ] ssid ];
:local DateTime ([ / system clock get date ] . " " . [ / system clock get time ]); :local DateTime ([ /system/clock/get date ] . " " . [ /system/clock/get time ]);
:local Vendor [ $GetMacVendor ($RegVal->"mac-address") ]; :local Vendor [ $GetMacVendor ($RegVal->"mac-address") ];
:local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \ :local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \
"first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface"); "first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface");
$LogPrintExit2 info $0 $Message false; $LogPrintExit2 info $0 $Message false;
/ interface wireless access-list add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes; /interface/wireless/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
$SendNotification2 ({ origin=$0; \ $SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "mobile-phone" ] . $RegVal->"mac-address" . " connected to " . $RegVal->"ssid"); \ subject=([ $SymbolForNotification "mobile-phone" ] . $RegVal->"mac-address" . " connected to " . $RegVal->"ssid"); \
message=("A device with unknown MAC address connected to " . $RegVal->"ssid" . " on " . $Identity . ".\n\n" . \ message=("A device with unknown MAC address connected to " . $RegVal->"ssid" . " on " . $Identity . ".\n\n" . \

View file

@ -26,48 +26,48 @@
$ScriptLock $0 false 10; $ScriptLock $0 false 10;
:if ([ :len [ / %PATH% access-list find where comment="--- collected above ---" disabled ] ] = 0) do={ :if ([ :len [ /%PATH%/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
/ %PATH% access-list add comment="--- collected above ---" disabled=yes; /%PATH%/access-list/add comment="--- collected above ---" disabled=yes;
$LogPrintExit2 warning $0 ("Added disabled access-list entry with comment '--- collected above ---'.") false; $LogPrintExit2 warning $0 ("Added disabled access-list entry with comment '--- collected above ---'.") false;
} }
:local PlaceBefore ([ / %PATH% access-list find where comment="--- collected above ---" disabled ]->0); :local PlaceBefore ([ /%PATH%/access-list/find where comment="--- collected above ---" disabled ]->0);
:foreach Reg in=[ / %PATH% registration-table find ] do={ :foreach Reg in=[ /%PATH%/registration-table/find ] do={
:local RegVal; :local RegVal;
:do { :do {
:set RegVal [ / %PATH% registration-table get $Reg ]; :set RegVal [ /%PATH%/registration-table/get $Reg ];
} on-error={ } on-error={
$LogPrintExit2 debug $0 ("Device already gone... Ignoring.") false; $LogPrintExit2 debug $0 ("Device already gone... Ignoring.") false;
} }
:if ([ :len ($RegVal->"mac-address") ] > 0) do={ :if ([ :len ($RegVal->"mac-address") ] > 0) do={
:local AccessList ([ / %PATH% access-list find where mac-address=($RegVal->"mac-address") ]->0); :local AccessList ([ /%PATH%/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={ :if ([ :len $AccessList ] > 0) do={
$LogPrintExit2 debug $0 ("MAC address " . $RegVal->"mac-address" . " already known: " . \ $LogPrintExit2 debug $0 ("MAC address " . $RegVal->"mac-address" . " already known: " . \
[ / %PATH% access-list get $AccessList comment ]) false; [ /%PATH%/access-list/get $AccessList comment ]) false;
} }
:if ([ :len $AccessList ] = 0) do={ :if ([ :len $AccessList ] = 0) do={
:local Address "no dhcp lease"; :local Address "no dhcp lease";
:local DnsName "no dhcp lease"; :local DnsName "no dhcp lease";
:local HostName "no dhcp lease"; :local HostName "no dhcp lease";
:local Lease ([ / ip dhcp-server lease find where mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0); :local Lease ([ /ip/dhcp-server/lease/find where mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0);
:if ([ :len $Lease ] > 0) do={ :if ([ :len $Lease ] > 0) do={
:set Address [ / ip dhcp-server lease get $Lease address ]; :set Address [ /ip/dhcp-server/lease/get $Lease address ];
:set HostName [ $EitherOr [ / ip dhcp-server lease get $Lease host-name ] "no hostname" ]; :set HostName [ $EitherOr [ /ip/dhcp-server/lease/get $Lease host-name ] "no hostname" ];
:set DnsName "no dns name"; :set DnsName "no dns name";
:local DnsRec ([ / ip dns static find where address=$Address ]->0); :local DnsRec ([ /ip/dns/static/find where address=$Address ]->0);
:if ([ :len $DnsRec ] > 0) do={ :if ([ :len $DnsRec ] > 0) do={
:set DnsName [ / ip dns static get $DnsRec name ]; :set DnsName [ /ip/dns/static/get $DnsRec name ];
} }
} }
:set ($RegVal->"ssid") [ / interface wireless get [ find where name=($RegVal->"interface") ] ssid ]; :set ($RegVal->"ssid") [ /interface/wireless/get [ find where name=($RegVal->"interface") ] ssid ];
:local DateTime ([ / system clock get date ] . " " . [ / system clock get time ]); :local DateTime ([ /system/clock/get date ] . " " . [ /system/clock/get time ]);
:local Vendor [ $GetMacVendor ($RegVal->"mac-address") ]; :local Vendor [ $GetMacVendor ($RegVal->"mac-address") ];
:local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \ :local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \
"first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface"); "first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface");
$LogPrintExit2 info $0 $Message false; $LogPrintExit2 info $0 $Message false;
/ %PATH% access-list add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes; /%PATH%/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
$SendNotification2 ({ origin=$0; \ $SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "mobile-phone" ] . $RegVal->"mac-address" . " connected to " . $RegVal->"ssid"); \ subject=([ $SymbolForNotification "mobile-phone" ] . $RegVal->"mac-address" . " connected to " . $RegVal->"ssid"); \
message=("A device with unknown MAC address connected to " . $RegVal->"ssid" . " on " . $Identity . ".\n\n" . \ message=("A device with unknown MAC address connected to " . $RegVal->"ssid" . " on " . $Identity . ".\n\n" . \

View file

@ -56,20 +56,20 @@ $WaitFullyConnected;
} }
:local Seen [ :toarray "" ]; :local Seen [ :toarray "" ];
:local Date [ / system clock get date ]; :local Date [ /system/clock/get date ];
:local NewPsk [ $GeneratePSK $Date ]; :local NewPsk [ $GeneratePSK $Date ];
:foreach AccList in=[ / caps-man access-list find where comment~$DailyPskMatchComment ] do={ :foreach AccList in=[ /caps-man/access-list/find where comment~$DailyPskMatchComment ] do={
:local Ssid [ / caps-man access-list get $AccList ssid-regexp ]; :local Ssid [ /caps-man/access-list/get $AccList ssid-regexp ];
:local Configuration [ / caps-man configuration get ([ find where ssid=$Ssid ]->0) name ]; :local Configuration [ /caps-man/configuration/get ([ find where ssid=$Ssid ]->0) name ];
:local OldPsk [ / caps-man access-list get $AccList private-passphrase ]; :local OldPsk [ /caps-man/access-list/get $AccList private-passphrase ];
:local Skip 0; :local Skip 0;
:if ($NewPsk != $OldPsk) do={ :if ($NewPsk != $OldPsk) do={
$LogPrintExit2 info $0 ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")") false; $LogPrintExit2 info $0 ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")") false;
/ caps-man access-list set $AccList private-passphrase=$NewPsk; /caps-man/access-list/set $AccList private-passphrase=$NewPsk;
:if ([ :len [ / caps-man interface find where configuration=$Configuration ] ] > 0) do={ :if ([ :len [ /caps-man/interface/find where configuration=$Configuration ] ] > 0) do={
:foreach SeenSsid in=$Seen do={ :foreach SeenSsid in=$Seen do={
:if ($SeenSsid = $Ssid) do={ :if ($SeenSsid = $Ssid) do={
$LogPrintExit2 debug $0 ("Already sent a mail for SSID " . $Ssid . ", skipping.") false; $LogPrintExit2 debug $0 ("Already sent a mail for SSID " . $Ssid . ", skipping.") false;

View file

@ -56,20 +56,20 @@ $WaitFullyConnected;
} }
:local Seen [ :toarray "" ]; :local Seen [ :toarray "" ];
:local Date [ / system clock get date ]; :local Date [ /system/clock/get date ];
:local NewPsk [ $GeneratePSK $Date ]; :local NewPsk [ $GeneratePSK $Date ];
:foreach AccList in=[ / interface wireless access-list find where comment~$DailyPskMatchComment ] do={ :foreach AccList in=[ /interface/wireless/access-list/find where comment~$DailyPskMatchComment ] do={
:local IntName [ / interface wireless access-list get $AccList interface ]; :local IntName [ /interface/wireless/access-list/get $AccList interface ];
:local Ssid [ / interface wireless get $IntName ssid ]; :local Ssid [ /interface/wireless/get $IntName ssid ];
:local OldPsk [ / interface wireless access-list get $AccList private-pre-shared-key ]; :local OldPsk [ /interface/wireless/access-list/get $AccList private-pre-shared-key ];
:local Skip 0; :local Skip 0;
:if ($NewPsk != $OldPsk) do={ :if ($NewPsk != $OldPsk) do={
$LogPrintExit2 info $0 ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")") false; $LogPrintExit2 info $0 ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")") false;
/ interface wireless access-list set $AccList private-pre-shared-key=$NewPsk; /interface/wireless/access-list/set $AccList private-pre-shared-key=$NewPsk;
:if ([ :len [ / interface wireless find where name=$IntName disabled=no ] ] = 1) do={ :if ([ :len [ /interface/wireless/find where name=$IntName disabled=no ] ] = 1) do={
:foreach SeenSsid in=$Seen do={ :foreach SeenSsid in=$Seen do={
:if ($SeenSsid = $Ssid) do={ :if ($SeenSsid = $Ssid) do={
$LogPrintExit2 debug $0 ("Already sent a mail for SSID " . $Ssid . ", skipping.") false; $LogPrintExit2 debug $0 ("Already sent a mail for SSID " . $Ssid . ", skipping.") false;

View file

@ -57,25 +57,25 @@ $WaitFullyConnected;
} }
:local Seen [ :toarray "" ]; :local Seen [ :toarray "" ];
:local Date [ / system clock get date ]; :local Date [ /system/clock/get date ];
:local NewPsk [ $GeneratePSK $Date ]; :local NewPsk [ $GeneratePSK $Date ];
:foreach AccList in=[ / %PATH% access-list find where comment~$DailyPskMatchComment ] do={ :foreach AccList in=[ /%PATH%/access-list/find where comment~$DailyPskMatchComment ] do={
:local IntName [ / interface wireless access-list get $AccList interface ]; :local IntName [ /interface/wireless/access-list/get $AccList interface ];
:local Ssid [ / interface wireless get $IntName ssid ]; :local Ssid [ /interface/wireless/get $IntName ssid ];
:local Ssid [ / caps-man access-list get $AccList ssid-regexp ]; :local Ssid [ /caps-man/access-list/get $AccList ssid-regexp ];
:local Configuration [ / caps-man configuration get ([ find where ssid=$Ssid ]->0) name ]; :local Configuration [ /caps-man/configuration/get ([ find where ssid=$Ssid ]->0) name ];
:local OldPsk [ / interface wireless access-list get $AccList private-pre-shared-key ]; :local OldPsk [ /interface/wireless/access-list/get $AccList private-pre-shared-key ];
:local OldPsk [ / caps-man access-list get $AccList private-passphrase ]; :local OldPsk [ /caps-man/access-list/get $AccList private-passphrase ];
:local Skip 0; :local Skip 0;
:if ($NewPsk != $OldPsk) do={ :if ($NewPsk != $OldPsk) do={
$LogPrintExit2 info $0 ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")") false; $LogPrintExit2 info $0 ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")") false;
/ interface wireless access-list set $AccList private-pre-shared-key=$NewPsk; /interface/wireless/access-list/set $AccList private-pre-shared-key=$NewPsk;
/ caps-man access-list set $AccList private-passphrase=$NewPsk; /caps-man/access-list/set $AccList private-passphrase=$NewPsk;
:if ([ :len [ / interface wireless find where name=$IntName disabled=no ] ] = 1) do={ :if ([ :len [ /interface/wireless/find where name=$IntName disabled=no ] ] = 1) do={
:if ([ :len [ / caps-man interface find where configuration=$Configuration ] ] > 0) do={ :if ([ :len [ /caps-man/interface/find where configuration=$Configuration ] ] > 0) do={
:foreach SeenSsid in=$Seen do={ :foreach SeenSsid in=$Seen do={
:if ($SeenSsid = $Ssid) do={ :if ($SeenSsid = $Ssid) do={
$LogPrintExit2 debug $0 ("Already sent a mail for SSID " . $Ssid . ", skipping.") false; $LogPrintExit2 debug $0 ("Already sent a mail for SSID " . $Ssid . ", skipping.") false;

View file

@ -16,15 +16,15 @@
:global LogPrintExit2; :global LogPrintExit2;
:foreach Lease in=[ / ip dhcp-server lease find where dynamic=yes status=bound ] do={ :foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
:local LeaseVal [ / ip dhcp-server lease get $Lease ]; :local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:local NewComment; :local NewComment;
:local AccessList ([ / caps-man access-list find where mac-address=($LeaseVal->"mac-address") ]->0); :local AccessList ([ /caps-man/access-list/find where mac-address=($LeaseVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={ :if ([ :len $AccessList ] > 0) do={
:set NewComment [ / caps-man access-list get $AccessList comment ]; :set NewComment [ /caps-man/access-list/get $AccessList comment ];
} }
:if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={ :if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={
$LogPrintExit2 info $0 ("Updating comment for DHCP lease " . $LeaseVal->"mac-address" . ": " . $NewComment) false; $LogPrintExit2 info $0 ("Updating comment for DHCP lease " . $LeaseVal->"mac-address" . ": " . $NewComment) false;
/ ip dhcp-server lease set comment=$NewComment $Lease; /ip/dhcp-server/lease/set comment=$NewComment $Lease;
} }
} }

View file

@ -16,15 +16,15 @@
:global LogPrintExit2; :global LogPrintExit2;
:foreach Lease in=[ / ip dhcp-server lease find where dynamic=yes status=bound ] do={ :foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
:local LeaseVal [ / ip dhcp-server lease get $Lease ]; :local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:local NewComment; :local NewComment;
:local AccessList ([ / interface wireless access-list find where mac-address=($LeaseVal->"mac-address") ]->0); :local AccessList ([ /interface/wireless/access-list/find where mac-address=($LeaseVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={ :if ([ :len $AccessList ] > 0) do={
:set NewComment [ / interface wireless access-list get $AccessList comment ]; :set NewComment [ /interface/wireless/access-list/get $AccessList comment ];
} }
:if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={ :if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={
$LogPrintExit2 info $0 ("Updating comment for DHCP lease " . $LeaseVal->"mac-address" . ": " . $NewComment) false; $LogPrintExit2 info $0 ("Updating comment for DHCP lease " . $LeaseVal->"mac-address" . ": " . $NewComment) false;
/ ip dhcp-server lease set comment=$NewComment $Lease; /ip/dhcp-server/lease/set comment=$NewComment $Lease;
} }
} }

View file

@ -17,15 +17,15 @@
:global LogPrintExit2; :global LogPrintExit2;
:foreach Lease in=[ / ip dhcp-server lease find where dynamic=yes status=bound ] do={ :foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
:local LeaseVal [ / ip dhcp-server lease get $Lease ]; :local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:local NewComment; :local NewComment;
:local AccessList ([ / %PATH% access-list find where mac-address=($LeaseVal->"mac-address") ]->0); :local AccessList ([ /%PATH%/access-list/find where mac-address=($LeaseVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={ :if ([ :len $AccessList ] > 0) do={
:set NewComment [ / %PATH% access-list get $AccessList comment ]; :set NewComment [ /%PATH%/access-list/get $AccessList comment ];
} }
:if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={ :if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={
$LogPrintExit2 info $0 ("Updating comment for DHCP lease " . $LeaseVal->"mac-address" . ": " . $NewComment) false; $LogPrintExit2 info $0 ("Updating comment for DHCP lease " . $LeaseVal->"mac-address" . ": " . $NewComment) false;
/ ip dhcp-server lease set comment=$NewComment $Lease; /ip/dhcp-server/lease/set comment=$NewComment $Lease;
} }
} }

View file

@ -32,28 +32,28 @@ $ScriptLock $0 false 10;
:local CommentPrefix ("managed by " . $0 . " for "); :local CommentPrefix ("managed by " . $0 . " for ");
:local CommentString ("--- " . $0 . " above ---"); :local CommentString ("--- " . $0 . " above ---");
:if ([ :len [ / ip dns static find where comment=$CommentString name=- type=NXDOMAIN disabled ] ] = 0) do={ :if ([ :len [ /ip/dns/static/find where comment=$CommentString name=- type=NXDOMAIN disabled ] ] = 0) do={
/ ip dns static add comment=$CommentString name=- type=NXDOMAIN disabled=yes; /ip/dns/static/add comment=$CommentString name=- type=NXDOMAIN disabled=yes;
$LogPrintExit2 warning $0 ("Added disabled static dns record with comment '" . $CommentString . "'.") false; $LogPrintExit2 warning $0 ("Added disabled static dns record with comment '" . $CommentString . "'.") false;
} }
:local PlaceBefore ([ / ip dns static find where comment=$CommentString name=- type=NXDOMAIN disabled ]->0); :local PlaceBefore ([ /ip/dns/static/find where comment=$CommentString name=- type=NXDOMAIN disabled ]->0);
:foreach DnsRecord in=[ / ip dns static find where comment ~ $CommentPrefix ] do={ :foreach DnsRecord in=[ /ip/dns/static/find where comment ~ $CommentPrefix ] do={
:local DnsRecordVal [ / ip dns static get $DnsRecord ]; :local DnsRecordVal [ /ip/dns/static/get $DnsRecord ];
:local MacAddress [ $CharacterReplace ($DnsRecordVal->"comment") $CommentPrefix "" ]; :local MacAddress [ $CharacterReplace ($DnsRecordVal->"comment") $CommentPrefix "" ];
:if ([ :len [ / ip dhcp-server lease find where mac-address=$MacAddress address=($DnsRecordVal->"address") status=bound ] ] > 0) do={ :if ([ :len [ /ip/dhcp-server/lease/find where mac-address=$MacAddress address=($DnsRecordVal->"address") status=bound ] ] > 0) do={
$LogPrintExit2 debug $0 ("Lease for " . $MacAddress . " (" . $DnsRecordVal->"name" . ") still exists. Not deleting DNS entry.") false; $LogPrintExit2 debug $0 ("Lease for " . $MacAddress . " (" . $DnsRecordVal->"name" . ") still exists. Not deleting DNS entry.") false;
} else={ } else={
:local Found false; :local Found false;
$LogPrintExit2 info $0 ("Lease expired for " . $MacAddress . " (" . $DnsRecordVal->"name" . "), deleting DNS entry.") false; $LogPrintExit2 info $0 ("Lease expired for " . $MacAddress . " (" . $DnsRecordVal->"name" . "), deleting DNS entry.") false;
/ ip dns static remove $DnsRecord; /ip/dns/static/remove $DnsRecord;
} }
} }
:foreach Lease in=[ / ip dhcp-server lease find where status=bound ] do={ :foreach Lease in=[ /ip/dhcp-server/lease/find where status=bound ] do={
:local LeaseVal; :local LeaseVal;
:do { :do {
:set LeaseVal [ / ip dhcp-server lease get $Lease ]; :set LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
} on-error={ } on-error={
$LogPrintExit2 debug $0 ("A lease just vanished, ignoring.") false; $LogPrintExit2 debug $0 ("A lease just vanished, ignoring.") false;
} }
@ -65,19 +65,19 @@ $ScriptLock $0 false 10;
[ $CharacterReplace ($LeaseVal->"host-name") " " "" ] ]; [ $CharacterReplace ($LeaseVal->"host-name") " " "" ] ];
:local Fqdn ($HostName . "." . [ $IfThenElse ($ServerNameInZone = true) ($LeaseVal->"server" . ".") ] . $Zone); :local Fqdn ($HostName . "." . [ $IfThenElse ($ServerNameInZone = true) ($LeaseVal->"server" . ".") ] . $Zone);
:local DnsRecord [ / ip dns static find where name=$Fqdn ]; :local DnsRecord [ /ip/dns/static/find where name=$Fqdn ];
:if ([ :len $DnsRecord ] > 0) do={ :if ([ :len $DnsRecord ] > 0) do={
:local DnsIp [ / ip dns static get $DnsRecord address ]; :local DnsIp [ /ip/dns/static/get $DnsRecord address ];
:local DupMacLeases [ / ip dhcp-server lease find where mac-address=($LeaseVal->"mac-address") status=bound ]; :local DupMacLeases [ /ip/dhcp-server/lease/find where mac-address=($LeaseVal->"mac-address") status=bound ];
:if ([ :len $DupMacLeases ] > 1) do={ :if ([ :len $DupMacLeases ] > 1) do={
:set ($LeaseVal->"address") [ / ip dhcp-server lease get ($DupMacLeases->([ :len $DupMacLeases ] - 1)) address ]; :set ($LeaseVal->"address") [ /ip/dhcp-server/lease/get ($DupMacLeases->([ :len $DupMacLeases ] - 1)) address ];
} }
:if ([ :len ($LeaseVal->"host-name") ] > 0) do={ :if ([ :len ($LeaseVal->"host-name") ] > 0) do={
:local HostNameLeases [ / ip dhcp-server lease find where host-name=($LeaseVal->"host-name") status=bound ]; :local HostNameLeases [ /ip/dhcp-server/lease/find where host-name=($LeaseVal->"host-name") status=bound ];
:if ([ :len $HostNameLeases ] > 1) do={ :if ([ :len $HostNameLeases ] > 1) do={
:set ($LeaseVal->"address") [ / ip dhcp-server lease get ($HostNameLeases->0) address ]; :set ($LeaseVal->"address") [ /ip/dhcp-server/lease/get ($HostNameLeases->0) address ];
} }
} }
@ -85,11 +85,11 @@ $ScriptLock $0 false 10;
$LogPrintExit2 debug $0 ("DNS entry for " . $Fqdn . " does not need updating.") false; $LogPrintExit2 debug $0 ("DNS entry for " . $Fqdn . " does not need updating.") false;
} else={ } else={
$LogPrintExit2 info $0 ("Replacing DNS entry for " . $Fqdn . ", new address is " . $LeaseVal->"address" . ".") false; $LogPrintExit2 info $0 ("Replacing DNS entry for " . $Fqdn . ", new address is " . $LeaseVal->"address" . ".") false;
/ ip dns static set name=$Fqdn address=($LeaseVal->"address") ttl=$Ttl comment=$Comment $DnsRecord; /ip/dns/static/set name=$Fqdn address=($LeaseVal->"address") ttl=$Ttl comment=$Comment $DnsRecord;
} }
} else={ } else={
$LogPrintExit2 info $0 ("Adding new DNS entry for " . $Fqdn . ", address is " . $LeaseVal->"address" . ".") false; $LogPrintExit2 info $0 ("Adding new DNS entry for " . $Fqdn . ", address is " . $LeaseVal->"address" . ".") false;
/ ip dns static add name=$Fqdn address=($LeaseVal->"address") ttl=$Ttl comment=$Comment place-before=$PlaceBefore; /ip/dns/static/add name=$Fqdn address=($LeaseVal->"address") ttl=$Ttl comment=$Comment place-before=$PlaceBefore;
} }
} else={ } else={
$LogPrintExit2 debug $0 ("No address available... Ignoring.") false; $LogPrintExit2 debug $0 ("No address available... Ignoring.") false;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Before After
Before After

View file

@ -15,8 +15,8 @@ entries in wireless access list.
Requirements and installation Requirements and installation
----------------------------- -----------------------------
Depending on whether you use CAPsMAN (`/ caps-man`) or local wireless Depending on whether you use CAPsMAN (`/caps-man`) or local wireless
interface (`/ interface wireless`) you need to install a different script. interface (`/interface/wireless`) you need to install a different script.
For CAPsMAN: For CAPsMAN:
@ -31,7 +31,7 @@ Usage and invocation
Run this script from a terminal: Run this script from a terminal:
/ system script run accesslist-duplicates.local; /system/script/run accesslist-duplicates.local;
![screenshot: example](accesslist-duplicates.d/01-example.avif) ![screenshot: example](accesslist-duplicates.d/01-example.avif)

View file

@ -45,11 +45,11 @@ Usage and invocation
Just run the script: Just run the script:
/ system script run backup-cloud; /system/script/run backup-cloud;
Creating a scheduler may be an option: Creating a scheduler may be an option:
/ system scheduler add interval=1w name=backup-cloud on-event="/ system script run backup-cloud;" start-time=09:20:00; /system/scheduler/add interval=1w name=backup-cloud on-event="/system/script/run backup-cloud;" start-time=09:20:00;
See also See also
-------- --------

View file

@ -9,8 +9,8 @@ Send backup via e-mail
Description Description
----------- -----------
This script sends binary backup (`/ system backup save`) and complete This script sends binary backup (`/system/backup/save`) and complete
configuration export (`/ export terse show-sensitive`) via e-mail. configuration export (`/export terse show-sensitive`) via e-mail.
Requirements and installation Requirements and installation
----------------------------- -----------------------------
@ -36,11 +36,11 @@ Usage and invocation
Just run the script: Just run the script:
/ system script run backup-email; /system/script/run backup-email;
Creating a scheduler may be an option: Creating a scheduler may be an option:
/ system scheduler add interval=1w name=backup-email on-event="/ system script run backup-email;" start-time=09:15:00; /system/scheduler/add interval=1w name=backup-email on-event="/system/script/run backup-email;" start-time=09:15:00;
See also See also
-------- --------

View file

@ -27,11 +27,11 @@ Usage and invocation
Just run the script: Just run the script:
/ system script run backup-partition; /system/script/run backup-partition;
Creating a scheduler may be an option: 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; /system/scheduler/add interval=1w name=backup-partition on-event="/system/script/run backup-partition;" start-time=09:30:00;
See also See also
-------- --------

View file

@ -9,8 +9,8 @@ Upload backup to server
Description Description
----------- -----------
This script uploads binary backup (`/ system backup save`) and complete This script uploads binary backup (`/system/backup/save`) and complete
configuration export (`/ export terse show-sensitive`) to external server. configuration export (`/export terse show-sensitive`) to external server.
> ⚠️ **Warning**: The used command can hit errors that a script can not handle. > ⚠️ **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 > This may result in script termination (where no notification is sent) or
@ -60,11 +60,11 @@ Usage and invocation
Just run the script: Just run the script:
/ system script run backup-upload; /system/script/run backup-upload;
Creating a scheduler may be an option: Creating a scheduler may be an option:
/ system scheduler add interval=1w name=backup-upload on-event="/ system script run backup-upload;" start-time=09:25:00; /system/scheduler/add interval=1w name=backup-upload on-event="/system/script/run backup-upload;" start-time=09:25:00;
See also See also
-------- --------

View file

@ -24,7 +24,7 @@ Just install the script on CAPsMAN device:
Optionally add a scheduler to run after startup: 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; /system/scheduler/add name=capsman-download-packages on-event="/system/script/run capsman-download-packages;" start-time=startup;
Packages available in local storage in older version are downloaded Packages available in local storage in older version are downloaded
unconditionally. The script tries to download missing packages by guessing unconditionally. The script tries to download missing packages by guessing
@ -35,7 +35,7 @@ Usage and invocation
Run the script manually: Run the script manually:
/ system script run capsman-download-packages; /system/script/run capsman-download-packages;
... or from scheduler. ... or from scheduler.

View file

@ -33,7 +33,7 @@ that script when required.
Alternatively run it manually: Alternatively run it manually:
/ system script run capsman-rolling-upgrade; /system/script/run capsman-rolling-upgrade;
See also See also
-------- --------

View file

@ -33,7 +33,7 @@ Usage and invocation
Run the script to renew certificates issued from a local CA. Run the script to renew certificates issued from a local CA.
/ system script run certificate-renew-issued; /system/script/run certificate-renew-issued;
Only scripts with a remaining lifetime of three weeks or less are renewed. Only scripts with a remaining lifetime of three weeks or less are renewed.
The old certificate is revoked automatically. If a passphrase for a specific The old certificate is revoked automatically. If a passphrase for a specific

View file

@ -44,15 +44,15 @@ Usage and invocation
Just run the script: Just run the script:
/ system script run check-certificates; /system/script/run check-certificates;
... or create a scheduler for periodic execution: ... or create a scheduler for periodic execution:
/ system scheduler add interval=1d name=check-certificates on-event="/ system script run check-certificates;" start-time=startup; /system/scheduler/add interval=1d name=check-certificates on-event="/system/script/run check-certificates;" start-time=startup;
Alternatively running on startup may be desired: Alternatively running on startup may be desired:
/ system scheduler add name=check-certificates-startup on-event="/ system script run check-certificates;" start-time=startup; /system/scheduler/add name=check-certificates-startup on-event="/system/script/run check-certificates;" start-time=startup;
See also See also
-------- --------

View file

@ -21,7 +21,7 @@ Note that bad initial state will not trigger an event.
Only sensors available in hardware can be checked. See what your Only sensors available in hardware can be checked. See what your
hardware supports: hardware supports:
/ system health print; /system/health/print;
### Sample notifications ### Sample notifications
@ -45,7 +45,7 @@ Requirements and installation
Just install the script and create a scheduler: Just install the script and create a scheduler:
$ScriptInstallUpdate check-health; $ScriptInstallUpdate check-health;
/ system scheduler add interval=1m name=check-health on-event="/ system script run check-health;" start-time=startup; /system/scheduler/add interval=1m name=check-health on-event="/system/script/run check-health;" start-time=startup;
Configuration Configuration
------------- -------------

View file

@ -30,7 +30,7 @@ Just install the script:
... and create a scheduler: ... and create a scheduler:
/ system scheduler add interval=1d name=check-lte-firmware-upgrade on-event="/ system script run check-lte-firmware-upgrade;" start-time=startup; /system/scheduler/add interval=1d name=check-lte-firmware-upgrade on-event="/system/script/run check-lte-firmware-upgrade;" start-time=startup;
Configuration Configuration
------------- -------------

View file

@ -41,7 +41,7 @@ Just install the script:
And add a scheduler for automatic update notification: And add a scheduler for automatic update notification:
/ system scheduler add interval=1d name=check-routeros-update on-event="/ system script run check-routeros-update;" start-time=startup; /system/scheduler/add interval=1d name=check-routeros-update on-event="/system/script/run check-routeros-update;" start-time=startup;
Configuration Configuration
------------- -------------
@ -65,7 +65,7 @@ Usage and invocation
Be notified when run from scheduler or run it manually: Be notified when run from scheduler or run it manually:
/ system script run check-routeros-update; /system/script/run check-routeros-update;
If an update is found you can install it right away. If an update is found you can install it right away.

View file

@ -22,8 +22,8 @@ and modify it to your needs.
Requirements and installation Requirements and installation
----------------------------- -----------------------------
Depending on whether you use CAPsMAN (`/ caps-man`) or local wireless Depending on whether you use CAPsMAN (`/caps-man`) or local wireless
interface (`/ interface wireless`) you need to install a different script. interface (`/interface/wireless`) you need to install a different script.
For CAPsMAN: For CAPsMAN:

View file

@ -21,8 +21,8 @@ Requirements and installation
Just install this script. Just install this script.
Depending on whether you use CAPsMAN (`/ caps-man`) or local wireless Depending on whether you use CAPsMAN (`/caps-man`) or local wireless
interface (`/ interface wireless`) you need to install a different script. interface (`/interface/wireless`) you need to install a different script.
For CAPsMAN: For CAPsMAN:
@ -34,8 +34,8 @@ For local interface:
And add schedulers to run the script: And add schedulers to run the script:
/ system scheduler add interval=1d name=daily-psk-nightly on-event="/ system script run daily-psk.local;" start-date=may/23/2018 start-time=03:00:00; /system/scheduler/add interval=1d name=daily-psk-nightly on-event="/system/script/run daily-psk.local;" start-date=may/23/2018 start-time=03:00:00;
/ system scheduler add name=daily-psk-startup on-event="/ system script run daily-psk.local;" start-time=startup; /system/scheduler/add name=daily-psk-startup on-event="/system/script/run daily-psk.local;" start-time=startup;
These will update the passphrase on boot and nightly at 3:00. These will update the passphrase on boot and nightly at 3:00.
@ -49,7 +49,7 @@ The configuration goes to `global-config-overlay`, these are the parameters:
Then add an access list entry: Then add an access list entry:
/ interface wireless access-list add comment="Daily PSK" interface=wl-daily private-pre-shared-key="ToBeChangedDaily"; /interface/wireless/access-list/add comment="Daily PSK" interface=wl-daily private-pre-shared-key="ToBeChangedDaily";
Also notification settings are required for e-mail, Also notification settings are required for e-mail,
[matrix](mod/notification-matrix.md) and/or [matrix](mod/notification-matrix.md) and/or

View file

@ -15,8 +15,8 @@ from wireless access list.
Requirements and installation Requirements and installation
----------------------------- -----------------------------
Depending on whether you use CAPsMAN (`/ caps-man`) or local wireless Depending on whether you use CAPsMAN (`/caps-man`) or local wireless
interface (`/ interface wireless`) you need to install a different script. interface (`/interface/wireless`) you need to install a different script.
For CAPsMAN: For CAPsMAN:

View file

@ -23,7 +23,7 @@ Then run it from dhcp server as lease script. You may want to use
A scheduler cares about cleanup: A scheduler cares about cleanup:
/ system scheduler add interval=15m name=dhcp-to-dns on-event="/ system script run dhcp-to-dns;" start-time=startup; /system/scheduler/add interval=15m name=dhcp-to-dns on-event="/system/script/run dhcp-to-dns;" start-time=startup;
Configuration Configuration
------------- -------------

View file

@ -21,7 +21,7 @@ Requirements and installation
Just install the script and create a scheduler: Just install the script and create a scheduler:
$ScriptInstallUpdate firmware-upgrade-reboot; $ScriptInstallUpdate firmware-upgrade-reboot;
/ system scheduler add name=firmware-upgrade-reboot on-event="/ system script run firmware-upgrade-reboot;" start-time=startup; /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. Enjoy firmware being up to date and in sync with RouterOS.

View file

@ -27,7 +27,7 @@ Just install the script:
... and add it to your scheduler, for example in combination with the module ... and add it to your scheduler, for example in combination with the module
to [manage VLANs on bridge ports](mod/bridge-port-vlan.md): to [manage VLANs on bridge ports](mod/bridge-port-vlan.md):
/ system scheduler add name=bridge-port-vlan on-event="/ system script run global-wait; :global BridgePortVlan; \$BridgePortVlan default;" start-time=startup; /system/scheduler/add name=bridge-port-vlan on-event="/system/script/run global-wait; :global BridgePortVlan; \$BridgePortVlan default;" start-time=startup;
See also See also
-------- --------

View file

@ -23,7 +23,7 @@ Just install the script:
... and create a scheduler: ... and create a scheduler:
/ system scheduler add interval=1m name=gps-track on-event="/ system script run gps-track;" start-time=startup; /system/scheduler/add interval=1m name=gps-track on-event="/system/script/run gps-track;" start-time=startup;
Configuration Configuration
------------- -------------
@ -32,7 +32,7 @@ The configuration goes to `global-config-overlay`, the only parameter is:
* `GpsTrackUrl`: the url to send json data to * `GpsTrackUrl`: the url to send json data to
The configured coordinate format (see `/ system gps`) defines the format The configured coordinate format (see `/system/gps`) defines the format
sent to the server. sent to the server.
--- ---

View file

@ -25,7 +25,7 @@ Then install the script:
Configure your hotspot to use this script as `on-login` script: Configure your hotspot to use this script as `on-login` script:
/ ip hotspot user profile set on-login=hotspot-to-wpa [ find ]; /ip/hotspot/user/profile/set on-login=hotspot-to-wpa [ find ];
### Automatic cleanup ### Automatic cleanup
@ -36,11 +36,11 @@ access list forever. Install the optional script for automatic cleanup:
Create a scheduler: Create a scheduler:
/ system scheduler add interval=1d name=hotspot-to-wpa-cleanup on-event="/ system script run hotspot-to-wpa-cleanup;" start-time=startup; /system/scheduler/add interval=1d name=hotspot-to-wpa-cleanup on-event="/system/script/run hotspot-to-wpa-cleanup;" start-time=startup;
And add the lease script to your wpa interfaces' dhcp server: And add the lease script to your wpa interfaces' dhcp server:
/ ip dhcp-server set lease-script=lease-script [ find where name~"wpa" ]; /ip/dhcp-server/set lease-script=lease-script [ find where name~"wpa" ];
Configuration Configuration
------------- -------------
@ -51,8 +51,8 @@ entries are to be added.
Create hotspot login credentials: Create hotspot login credentials:
/ ip hotspot user add add comment="Test User 1" name=user1 password=v3ry; /ip/hotspot/user/add comment="Test User 1" name=user1 password=v3ry;
/ ip hotspot user add add comment="Test User 2" name=user2 password=s3cr3t; /ip/hotspot/user/add comment="Test User 2" name=user2 password=s3cr3t;
Additionally templates can be created to give more options for access list: Additionally templates can be created to give more options for access list:
@ -66,12 +66,12 @@ Additionally templates can be created to give more options for access list:
For a hotspot called `example` the template could look like this: For a hotspot called `example` the template could look like this:
/ caps-man access-list add comment="hotspot-to-wpa template example" disabled=yes private-passphrase="ignore" ssid-regexp="^example\$" vlan-id=10 vlan-mode=use-tag; /caps-man/access-list/add comment="hotspot-to-wpa template example" disabled=yes private-passphrase="ignore" ssid-regexp="^example\$" vlan-id=10 vlan-mode=use-tag;
The same settings are available in hotspot user's comment and take precedence The same settings are available in hotspot user's comment and take precedence
over the template settings: over the template settings:
/ ip hotspot user add comment="private-passphrase=ignore, ssid-regexp=^example\\\$, vlan-id=10, vlan-mode=use-tag" name=user password=v3ry-s3cr3t; /ip/hotspot/user/add comment="private-passphrase=ignore, ssid-regexp=^example\\\$, vlan-id=10, vlan-mode=use-tag" name=user password=v3ry-s3cr3t;
Usage and invocation Usage and invocation
-------------------- --------------------

View file

@ -19,7 +19,7 @@ Just install the script:
... and make it run from scheduler: ... and make it run from scheduler:
/ system scheduler add name=ip-addr-bridge on-event="/ system script run ip-addr-bridge;" start-time=startup; /system/scheduler/add name=ip-addr-bridge on-event="/system/script/run ip-addr-bridge;" start-time=startup;
This will disable IP addresses on bridges without at lease one running port. This will disable IP addresses on bridges without at lease one running port.
The IP address is enabled if at least one port is running. The IP address is enabled if at least one port is running.

View file

@ -21,7 +21,7 @@ Just install the script:
This script is run from scheduler: This script is run from scheduler:
/ system scheduler add interval=1m name=ipsec-to-dns on-event="/ system script run ipsec-to-dns;" start-time=startup; /system/scheduler/add interval=1m name=ipsec-to-dns on-event="/system/script/run ipsec-to-dns;" start-time=startup;
Configuration Configuration
------------- -------------

View file

@ -23,14 +23,14 @@ Just install the script:
Your ISP needs to provide an IPv6 prefix, your device receives it via dhcp: Your ISP needs to provide an IPv6 prefix, your device receives it via dhcp:
/ ipv6 dhcp-client add add-default-route=yes interface=ppp-isp pool-name=isp request=prefix script=ipv6-update; /ipv6/dhcp-client/add add-default-route=yes interface=ppp-isp pool-name=isp request=prefix script=ipv6-update;
Note this already adds this script as `script`. The pool name (here: "`isp`") Note this already adds this script as `script`. The pool name (here: "`isp`")
is important, we need it later. is important, we need it later.
Also this expects there is an address assigned from pool to an interface: Also this expects there is an address assigned from pool to an interface:
/ ipv6 address add from-pool=isp interface=br-local; /ipv6/address/add from-pool=isp interface=br-local;
Sometimes dhcp client is stuck on reconnect and needs to be released. Sometimes dhcp client is stuck on reconnect and needs to be released.
Installing [ppp-on-up](ppp-on-up.md) may solve this. Installing [ppp-on-up](ppp-on-up.md) may solve this.
@ -41,7 +41,7 @@ Configuration
An address list entry is updated with current prefix and can be used in An address list entry is updated with current prefix and can be used in
firewall rules, comment has to be "`ipv6-pool-`" and actual pool name: firewall rules, comment has to be "`ipv6-pool-`" and actual pool name:
/ ipv6 firewall address-list add address=2003:cf:2f0f:de00::/56 comment=ipv6-pool-isp list=extern; /ipv6/firewall/address-list/add address=2003:cf:2f0f:de00::/56 comment=ipv6-pool-isp list=extern;
As this entry is mandatory it is created automatically if it does not exist, As this entry is mandatory it is created automatically if it does not exist,
with the comment also set for list. with the comment also set for list.
@ -50,13 +50,13 @@ Address list entries for specific interfaces can be updated as well. The
interface needs to get its address from pool `isp` and the address list entry interface needs to get its address from pool `isp` and the address list entry
has to be associated to an interface in comment: has to be associated to an interface in comment:
/ ipv6 firewall address-list add address=2003:cf:2f0f:de01::/64 comment="ipv6-pool-isp, interface=br-local" list=local; /ipv6/firewall/address-list/add address=2003:cf:2f0f:de01::/64 comment="ipv6-pool-isp, interface=br-local" list=local;
Static DNS records need a special comment to be updated. Again it has to Static DNS records need a special comment to be updated. Again it has to
start with "`ipv6-pool-`" and actual pool name, followed by a comma, start with "`ipv6-pool-`" and actual pool name, followed by a comma,
"`interface=`" and the name of interface this address is connected to: "`interface=`" and the name of interface this address is connected to:
/ ip dns static add address=2003:cf:2f0f:de00:1122:3344:5566:7788 comment="ipv6-pool-isp, interface=br-local" name=test.example.com ttl=15m; /ip/dns/static/add address=2003:cf:2f0f:de00:1122:3344:5566:7788 comment="ipv6-pool-isp, interface=br-local" name=test.example.com ttl=15m;
See also See also
-------- --------

View file

@ -32,7 +32,7 @@ Just install the script:
... and add it as `lease-script` to your dhcp server: ... and add it as `lease-script` to your dhcp server:
/ ip dhcp-server set lease-script=lease-script [ find ]; /ip/dhcp-server/set lease-script=lease-script [ find ];
See also See also
-------- --------

View file

@ -21,21 +21,21 @@ Usage and invocation
To switch the device to dark mode: To switch the device to dark mode:
/ system script run leds-night-mode; /system/script/run leds-night-mode;
... and back to normal mode: ... and back to normal mode:
/ system script run leds-day-mode; /system/script/run leds-day-mode;
To toggle between the two modes: To toggle between the two modes:
/ system script run leds-toggle-mode; /system/script/run leds-toggle-mode;
Add these schedulers to switch to dark mode in the evening and back to Add these schedulers to switch to dark mode in the evening and back to
normal mode in the morning: normal mode in the morning:
/ system scheduler add interval=1d name=leds-day-mode on-event="/ system script run leds-day-mode;" start-time=07:00:00; /system/scheduler/add interval=1d name=leds-day-mode on-event="/system/script/run leds-day-mode;" start-time=07:00:00;
/ system scheduler add interval=1d name=leds-night-mode on-event="/ system script run leds-night-mode;" start-time=21:00:00; /system/scheduler/add interval=1d name=leds-night-mode on-event="/system/script/run leds-night-mode;" start-time=21:00:00;
The script `leds-toggle-mode` can be used from [mode button](mode-button.md) The script `leds-toggle-mode` can be used from [mode button](mode-button.md)
to toggle mode. to toggle mode.

View file

@ -33,7 +33,7 @@ Just install the script:
... and add a scheduler: ... and add a scheduler:
/ system scheduler add interval=1m name=log-forward on-event="/ system script run log-forward;" start-time=startup; /system/scheduler/add interval=1m name=log-forward on-event="/system/script/run log-forward;" start-time=startup;
Configuration Configuration
------------- -------------

View file

@ -22,20 +22,20 @@ Just install the module:
Configuration Configuration
------------- -------------
The configuration goes to ports' comments (`/ interface bridge port`). The configuration goes to ports' comments (`/interface/bridge/port`).
/ interface bridge port add bridge=br-guest comment="default=dhcp-client, alt=br-guest" disabled=yes interface=en1; /interface/bridge/port/add bridge=br-guest comment="default=dhcp-client, alt=br-guest" disabled=yes interface=en1;
/ interface bridge port add bridge=br-intern comment="default=br-intern, alt=br-guest" interface=en2; /interface/bridge/port/add bridge=br-intern comment="default=br-intern, alt=br-guest" interface=en2;
/ interface bridge port add bridge=br-guest comment="default=br-guest, extra=br-extra" interface=en3; /interface/bridge/port/add bridge=br-guest comment="default=br-guest, extra=br-extra" interface=en3;
Also dhcp client can be handled: Also dhcp client can be handled:
/ ip dhcp-client add comment="toggle with bridge port" disabled=no interface=en1; /ip/dhcp-client/add comment="toggle with bridge port" disabled=no interface=en1;
Add a scheduler to start with default setup on system startup: Add a scheduler to start with default setup on system startup:
$ScriptInstallUpdate global-wait; $ScriptInstallUpdate global-wait;
/ system scheduler add name=bridge-port-vlan on-event="/ system script run global-wait; :global BridgePortTo; \$BridgePortTo default;" start-time=startup; /system/scheduler/add name=bridge-port-vlan on-event="/system/script/run global-wait; :global BridgePortTo; \$BridgePortTo default;" start-time=startup;
Usage and invocation Usage and invocation
-------------------- --------------------

View file

@ -23,24 +23,24 @@ Configuration
Using named VLANs you have to add comments in bridge vlan menu: Using named VLANs you have to add comments in bridge vlan menu:
/ interface bridge vlan add bridge=bridge comment=intern tagged=br-local vlan-ids=10; /interface/bridge/vlan/add bridge=bridge comment=intern tagged=br-local vlan-ids=10;
/ interface bridge vlan add bridge=bridge comment=geust tagged=br-local vlan-ids=20; /interface/bridge/vlan/add bridge=bridge comment=geust tagged=br-local vlan-ids=20;
/ interface bridge vlan add bridge=bridge comment=extra tagged=br-local vlan-ids=30; /interface/bridge/vlan/add bridge=bridge comment=extra tagged=br-local vlan-ids=30;
The configuration goes to ports' comments (`/ interface bridge port`). The configuration goes to ports' comments (`/interface/bridge/port`).
/ interface bridge port add bridge=bridge comment="default=dhcp-client, alt=guest" disabled=yes interface=en1; /interface/bridge/port/add bridge=bridge comment="default=dhcp-client, alt=guest" disabled=yes interface=en1;
/ interface bridge port add bridge=bridge comment="default=intern, alt=guest, extra=30" interface=en2; /interface/bridge/port/add bridge=bridge comment="default=intern, alt=guest, extra=30" interface=en2;
/ interface bridge port add bridge=bridge comment="default=guest, extra=extra" interface=en3; /interface/bridge/port/add bridge=bridge comment="default=guest, extra=extra" interface=en3;
Also dhcp client can be handled: Also dhcp client can be handled:
/ ip dhcp-client add comment="toggle with bridge port" disabled=no interface=en1; /ip/dhcp-client/add comment="toggle with bridge port" disabled=no interface=en1;
Add a scheduler to start with default setup on system startup: Add a scheduler to start with default setup on system startup:
$ScriptInstallUpdate global-wait; $ScriptInstallUpdate global-wait;
/ system scheduler add name=bridge-port-vlan on-event="/ system script run global-wait; :global BridgePortVlan; \$BridgePortVlan default;" start-time=startup; /system/scheduler/add name=bridge-port-vlan on-event="/system/script/run global-wait; :global BridgePortVlan; \$BridgePortVlan default;" start-time=startup;
Usage and invocation Usage and invocation
-------------------- --------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Before After
Before After

View file

@ -24,7 +24,7 @@ Usage and invocation
Call the function `$InspectVar` with a variable as parameter: Call the function `$InspectVar` with a variable as parameter:
$InspectVar $ModeButton $InspectVar $ModeButton;
![InspectVar](inspectvar.d/inspectvar.avif) ![InspectVar](inspectvar.d/inspectvar.avif)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Before After
Before After

View file

@ -42,7 +42,7 @@ 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). [well-known uri](https://spec.matrix.org/latest/client-server-api/#well-known-uri).
For "*matrix.org*" this query is: For "*matrix.org*" this query is:
/ tool fetch "https://matrix.org/.well-known/matrix/client" output=user; /tool/fetch "https://matrix.org/.well-known/matrix/client" output=user;
![home server](notification-matrix.d/01-home-server.avif) ![home server](notification-matrix.d/01-home-server.avif)
@ -59,7 +59,7 @@ account must be sent to the home server via
We use the home server discovered above, "*matrix-client.matrix.org*". We use the home server discovered above, "*matrix-client.matrix.org*".
The user is "*example*" and password is "*v3ry-s3cr3t*". 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; /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) ![access token](notification-matrix.d/02-access-token.avif)
@ -80,7 +80,7 @@ this can be done with
Make sure to replace room id ("*!*" is escaped with "*%21*") and access token Make sure to replace room id ("*!*" is escaped with "*%21*") and access token
with your data. 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; /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) ![join room](notification-matrix.d/03-join-room.avif)

View file

@ -1,3 +1,3 @@
#!rsc by RouterOS #!rsc by RouterOS
:put ("Hello World from " . [ / system identity get name ] . "!"); :put ("Hello World from " . [ /system/identity/get name ] . "!");

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Before After
Before After

View file

@ -37,7 +37,7 @@ Usage and invocation
The function `$ScriptRunOnce` expects an URL (or name if The function `$ScriptRunOnce` expects an URL (or name if
`ScriptRunOnceBaseUrl` is given) pointing to a script as parameter. `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 https://git.eworm.de/cgit/routeros-scripts/plain/doc/mod/scriptrunonce.d/hello-world.rsc;
![ScriptRunOnce](scriptrunonce.d/scriptrunonce.avif) ![ScriptRunOnce](scriptrunonce.d/scriptrunonce.avif)

View file

@ -13,17 +13,17 @@ This script extend the functionality of mode button. Instead of just one
you can trigger several actions by pressing the mode button several times. you can trigger several actions by pressing the mode button several times.
The hardware needs to have a mode button, see The hardware needs to have a mode button, see
`/ system routerboard mode-button`. Starting with RouterOS 6.47beta60 you `/system/routerboard/mode-button`. Starting with RouterOS 6.47beta60 you
can configure the reset button to act the same, see can configure the reset button to act the same, see
`/ system routerboard reset-button`. `/system/routerboard/reset-button`.
Copy this code to terminal to check: Copy this code to terminal to check:
``` ```
:if ([ :len [ /system routerboard mode-button print as-value ] ] > 0) do={ :if ([ :len [ /system/routerboard/mode-button/print as-value ] ] > 0) do={
:put "Mode button is supported."; :put "Mode button is supported.";
} else={ } else={
:if ([ :len [ /system routerboard reset-button print as-value ] ] > 0) do={ :if ([ :len [ /system/routerboard/reset-button/print as-value ] ] > 0) do={
:put "Mode button is not supported, but reset button is."; :put "Mode button is not supported, but reset button is.";
} else={ } else={
:put "Neither mode button nor reset button is supported."; :put "Neither mode button nor reset button is supported.";
@ -40,11 +40,11 @@ Just install the script:
Then configure the mode button to run `mode-button`: Then configure the mode button to run `mode-button`:
/ system routerboard mode-button set enabled=yes on-event="/ system script run mode-button;"; /system/routerboard/mode-button/set enabled=yes on-event="/system/script/run mode-button;";
To use the reset button instead: To use the reset button instead:
/ system routerboard reset-button set enabled=yes on-event="/ system script run mode-button;"; /system/routerboard/reset-button/set enabled=yes on-event="/system/script/run mode-button;";
Configuration Configuration
------------- -------------
@ -57,7 +57,7 @@ The configuration goes to `global-config-overlay`, these are the parameters:
Usage and invocation Usage and invocation
-------------------- --------------------
Press the mode button. :) Press the mode button. 😜
--- ---
[◀ Go back to main README](../README.md) [◀ Go back to main README](../README.md)

View file

@ -21,7 +21,7 @@ Just install the script:
Then add a scheduler to run it periodically: Then add a scheduler to run it periodically:
/ system scheduler add interval=1m name=netwatch-dns on-event="/ system script run netwatch-dns;" start-time=startup; /system/scheduler/add interval=1m name=netwatch-dns on-event="/system/script/run netwatch-dns;" start-time=startup;
Configuration Configuration
------------- -------------
@ -29,9 +29,9 @@ Configuration
The DNS and DoH servers to be checked have to be added to netwatch with The DNS and DoH servers to be checked have to be added to netwatch with
specific comment: specific comment:
/ tool netwatch add comment="doh, hostname=cloudflare-dns" host=1.1.1.1; /tool/netwatch/add comment="doh, hostname=cloudflare-dns" host=1.1.1.1;
/ tool netwatch add comment="dns, hostname=google-dns" host=8.8.8.8; /tool/netwatch/add comment="dns, hostname=google-dns" host=8.8.8.8;
/ tool netwatch add comment="doh, dns, hostname=quad-nine" host=9.9.9.10; /tool/netwatch/add comment="doh, dns, hostname=quad-nine" host=9.9.9.10;
This will configure *cloudflare-dns* for DoH (`https://1.1.1.1/dnsquery`), and This will configure *cloudflare-dns* for DoH (`https://1.1.1.1/dnsquery`), and
*google-dns* and *quad-nine* for regular DNS (`8.8.8.8,9.9.9.10`) if up. *google-dns* and *quad-nine* for regular DNS (`8.8.8.8,9.9.9.10`) if up.
@ -39,15 +39,15 @@ If *cloudflare-dns* is down the script will fall back to *quad-nine* for DoH.
Giving a specific query url for DoH is possible: Giving a specific query url for DoH is possible:
/ tool netwatch add comment="doh, hostname=nextdns, doh-url=https://dns.nextdns.io/dns-query" host=199.247.16.158; /tool/netwatch/add comment="doh, hostname=nextdns, doh-url=https://dns.nextdns.io/dns-query" host=199.247.16.158;
Note that using a name in DoH url may introduce a chicken-and-egg issue! Note that using a name in DoH url may introduce a chicken-and-egg issue!
Sometimes using just one specific (possibly internal) DNS server may be Sometimes using just one specific (possibly internal) DNS server may be
desired, with fallback in case it fails. This is possible as well: desired, with fallback in case it fails. This is possible as well:
/ tool netwatch add comment="dns, hostname=pi-hole" host=10.0.0.10; /tool/netwatch/add comment="dns, hostname=pi-hole" host=10.0.0.10;
/ tool netwatch add comment="dns-fallback, hostname=cloudflare-dns" host=1.1.1.1; /tool/netwatch/add comment="dns-fallback, hostname=cloudflare-dns" host=1.1.1.1;
Tips & Tricks Tips & Tricks
------------- -------------
@ -57,7 +57,7 @@ Tips & Tricks
Netwatch entries can be created to work with both - this script and Netwatch entries can be created to work with both - this script and
[netwatch-notify](netwatch-notify.md). Just give options for both: [netwatch-notify](netwatch-notify.md). Just give options for both:
/ tool netwatch add comment="doh, notify, hostname=cloudflare-dns" host=1.1.1.1; /tool/netwatch/add comment="doh, notify, hostname=cloudflare-dns" host=1.1.1.1;
Also this allows to update host address, see option `resolve`. Also this allows to update host address, see option `resolve`.

View file

@ -10,7 +10,7 @@ Description
----------- -----------
This script sends notifications about host UP and DOWN events. In comparison This script sends notifications about host UP and DOWN events. In comparison
to just netwatch (`/ tool netwatch`) and its `up-script` and `down-script` to just netwatch (`/tool/netwatch`) and its `up-script` and `down-script`
this script implements a simple state machine and dependency model. Host this script implements a simple state machine and dependency model. Host
down events are triggered only if the host is down for several checks and down events are triggered only if the host is down for several checks and
optional parent host is not down to avoid false alerts. optional parent host is not down to avoid false alerts.
@ -29,14 +29,14 @@ Just install the script:
Then add a scheduler to run it periodically: Then add a scheduler to run it periodically:
/ system scheduler add interval=1m name=netwatch-notify on-event="/ system script run netwatch-notify;" start-time=startup; /system/scheduler/add interval=1m name=netwatch-notify on-event="/system/script/run netwatch-notify;" start-time=startup;
Configuration Configuration
------------- -------------
The hosts to be checked have to be added to netwatch with specific comment: 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" ]; /tool/netwatch/add comment="notify, hostname=example.com" host=[ :resolve "example.com" ];
### Hooks ### Hooks
@ -44,7 +44,7 @@ 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 (`down-hook`) when a notification is triggered. This has to be added in
comment, note that some characters need extra escaping: comment, note that some characters need extra escaping:
/ tool netwatch add comment=("notify, hostname=device, down-hook=/ interface ethernet \\{ disable \\\"en2\\\"; enable \\\"en2\\\"; \\}") host=10.0.0.20; /tool/netwatch/add comment=("notify, hostname=device, down-hook=/interface/ethernet \\{ disable \\\"en2\\\"; enable \\\"en2\\\"; \\}") host=10.0.0.20;
Also there is a `pre-down-hook` that fires at two thirds of failed checks 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 required for the notification. The idea is to fix the issue before a
@ -54,15 +54,15 @@ notification is sent.
The count threshould (default is 5 checks) is configurable as well: 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; /tool/netwatch/add comment="notify, hostname=example.com, count=10" host=104.18.144.11;
### Parents & dependencies ### Parents & dependencies
If the host is behind another checked host add a dependency, this will If the host is behind another checked host add a dependency, this will
suppress notification if the parent host is down: suppress notification if the parent host is down:
/ tool netwatch add comment="notify, hostname=gateway" host=93.184.216.1; /tool/netwatch/add comment="notify, hostname=gateway" host=93.184.216.1;
/ tool netwatch add comment="notify, hostname=example.com, parent=gateway" host=93.184.216.34; /tool/netwatch/add comment="notify, hostname=example.com, parent=gateway" host=93.184.216.34;
Note that every configured parent in a chain increases the check count Note that every configured parent in a chain increases the check count
threshould by one. threshould by one.
@ -72,7 +72,7 @@ threshould by one.
The host address can be updated dynamically. Give extra parameter `resolve` The host address can be updated dynamically. Give extra parameter `resolve`
with a resolvable name: with a resolvable name:
/ tool netwatch add comment="notify, hostname=example.com, resolve=example.com"; /tool/netwatch/add comment="notify, hostname=example.com, resolve=example.com";
But be warned: Dynamic updates will probably cause issues if the name has 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 more than one record in dns - a high rate of configuration changes (and flash
@ -84,7 +84,7 @@ Also suppressing the notification on host down is possible with parameter
`no-down-notification`. This may be desired for devices that are usually `no-down-notification`. This may be desired for devices that are usually
powered off, but accessibility is of interest. powered off, but accessibility is of interest.
/ tool netwatch add comment="notify, hostname=printer, no-down-notification" host=10.0.0.30; /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. Go and get your coffee ☕️ before sending the print job.
@ -101,8 +101,8 @@ Sometimes it is sufficient if one of a number of hosts is available. You can
make `netwatch-notify` check for that by adding several items with same make `netwatch-notify` check for that by adding several items with same
`hostname`. Note that `count` has to be multiplied to keep the actual time. `hostname`. Note that `count` has to be multiplied to keep the actual time.
/ tool netwatch add comment="notify, hostname=service, count=10" host=10.0.0.10; /tool/netwatch/add comment="notify, hostname=service, count=10" host=10.0.0.10;
/ tool netwatch add comment="notify, hostname=service, count=10" host=10.0.0.20; /tool/netwatch/add comment="notify, hostname=service, count=10" host=10.0.0.20;
### Checking internet connectivity ### Checking internet connectivity
@ -112,11 +112,11 @@ check `1.1.1.1` (Cloudflare DNS), `9.9.9.9` (Quad-nine DNS), `8.8.8.8`
(Google DNS) or any other reliable address that indicates internet (Google DNS) or any other reliable address that indicates internet
connectivity. connectivity.
/ tool netwatch add comment="notify, hostname=internet" host=1.1.1.1; /tool/netwatch/add comment="notify, hostname=internet" host=1.1.1.1;
A target like this suits well to be parent for other checks. A target like this suits well to be parent for other checks.
/ tool netwatch add comment="notify, hostname=example.com, parent=internet" host=93.184.216.34; /tool/netwatch/add comment="notify, hostname=example.com, parent=internet" host=93.184.216.34;
### Checking specific ISP ### Checking specific ISP
@ -124,12 +124,13 @@ Having several ISPs for redundancy a failed link may go unnoticed without
proper monitoring. You can use routing-mark to monitor specific connections. proper monitoring. You can use routing-mark to monitor specific connections.
Create a route and firewall mangle rule. Create a route and firewall mangle rule.
/ ip route add distance=1 gateway=isp1 routing-mark=via-isp1; /routing/table/add fib name=via-isp1;
/ ip firewall mangle add action=mark-routing chain=output new-routing-mark=via-isp1 dst-address=1.0.0.1 passthrough=yes; /ip/route/add distance=1 gateway=isp1 routing-table=via-isp1;
/ip/firewall/mangle/add action=mark-routing chain=output new-routing-mark=via-isp1 dst-address=1.0.0.1 passthrough=yes;
Finally monitor the address with `netwatch-notify`. Finally monitor the address with `netwatch-notify`.
/ tool netwatch add comment="notify, hostname=quad-one via isp1" host=1.0.0.1; /tool/netwatch/add comment="notify, hostname=quad-one via isp1" host=1.0.0.1;
Note that *all* traffic to the given address is routed that way. In case of Note that *all* traffic to the given address is routed that way. In case of
link failure this address is not available, so use something reliable but link failure this address is not available, so use something reliable but
@ -141,7 +142,7 @@ non-essential. In this example the address `1.0.0.1` is used, the same service
Netwatch entries can be created to work with both - this script and Netwatch entries can be created to work with both - this script and
[netwatch-dns](netwatch-dns.md). Just give options for both: [netwatch-dns](netwatch-dns.md). Just give options for both:
/ tool netwatch add comment="doh, notify, hostname=cloudflare-dns" host=1.1.1.1; /tool/netwatch/add comment="doh, notify, hostname=cloudflare-dns" host=1.1.1.1;
See also See also
-------- --------

View file

@ -16,8 +16,8 @@ Requirements and installation
Let's assume there is a remote log action and associated logging rule: Let's assume there is a remote log action and associated logging rule:
/ system logging action set remote=10.0.0.1 [ find where name="remote" ]; /system/logging/action/set remote=10.0.0.1 [ find where name="remote" ];
/ system logging add action=remote topics=info; /system/logging/add action=remote topics=info;
Just install the script: Just install the script:
@ -25,7 +25,7 @@ Just install the script:
... and create a netwatch matching the IP address from logging action above: ... and create a netwatch matching the IP address from logging action above:
/ tool netwatch add down-script=netwatch-syslog host=10.0.0.1 up-script=netwatch-syslog; /tool/netwatch/add down-script=netwatch-syslog host=10.0.0.1 up-script=netwatch-syslog;
All logging rules are disabled when host is down. All logging rules are disabled when host is down.

View file

@ -22,7 +22,7 @@ Just install the script:
... and add a scheduler to run the script periodically: ... and add a scheduler to run the script periodically:
/ system scheduler add interval=20s name=ospf-to-leds on-event="/ system script run ospf-to-leds;" start-time=startup; /system/scheduler/add interval=20s name=ospf-to-leds on-event="/system/script/run ospf-to-leds;" start-time=startup;
Configuration Configuration
------------- -------------
@ -30,7 +30,7 @@ Configuration
The configuration goes to OSPF instance's comment. To visualize state for The configuration goes to OSPF instance's comment. To visualize state for
instance `default` via LED `user-led` set this: instance `default` via LED `user-led` set this:
/ routing ospf instance set default comment="ospf-to-leds, leds=user-led"; /routing/ospf/instance/set default comment="ospf-to-leds, leds=user-led";
--- ---
[◀ Go back to main README](../README.md) [◀ Go back to main README](../README.md)

View file

@ -10,7 +10,7 @@ Description
----------- -----------
In rare cases RouterOS fails to properly downlaod package on update In rare cases RouterOS fails to properly downlaod package on update
(`/ system package update install`), resulting in borked system with missing (`/system/package/update/install`), resulting in borked system with missing
packages. This script tries to avoid this situation by doing some basic packages. This script tries to avoid this situation by doing some basic
verification. verification.
@ -35,7 +35,7 @@ Usage and invocation
Alternatively run it manually: Alternatively run it manually:
/ system script run packages-update; /system/script/run packages-update;
See also See also
-------- --------

View file

@ -24,7 +24,7 @@ Just install the script:
... and make it the `on-up` script for ppp profile: ... and make it the `on-up` script for ppp profile:
/ ppp profile set on-up=ppp-on-up [ find ]; /ppp/profile/set on-up=ppp-on-up [ find ];
See also See also
-------- --------

View file

@ -36,7 +36,7 @@ addresses from pool if required.
Alternatively a scheduler can be created: Alternatively a scheduler can be created:
/ system scheduler add interval=5d name=rotate-ntp on-event="/ system script run rotate-ntp;" start-time=startup; /system/scheduler/add interval=5d name=rotate-ntp on-event="/system/script/run rotate-ntp;" start-time=startup;
--- ---
[◀ Go back to main README](../README.md) [◀ Go back to main README](../README.md)

View file

@ -30,7 +30,7 @@ The configuration goes to `global-config-overlay`, this is the only parameter:
Then enable SMS actions: Then enable SMS actions:
/ tool sms set allowed-number=+491234567890 receive-enabled=yes secret=s3cr3t; /tool/sms/set allowed-number=+491234567890 receive-enabled=yes secret=s3cr3t;
Usage and invocation Usage and invocation
-------------------- --------------------

View file

@ -26,7 +26,7 @@ Just install the script:
... and add a scheduler to run it periodically: ... and add a scheduler to run it periodically:
/ system scheduler add interval=2m name=sms-forward on-event="/ system script run sms-forward;" start-time=startup; /system/scheduler/add interval=2m name=sms-forward on-event="/system/script/run sms-forward;" start-time=startup;
Configuration Configuration
------------- -------------
@ -36,7 +36,7 @@ Notification settings are required for e-mail,
[telegram](mod/notification-telegram.md). Also you have to enable receiving [telegram](mod/notification-telegram.md). Also you have to enable receiving
of SMS: of SMS:
/ tool sms set receive-enabled=yes; /tool/sms/set receive-enabled=yes;
See also See also
-------- --------

View file

@ -22,7 +22,7 @@ Usage and invocation
Copy files with extension "`pub`" containing public SSH keys for your device. Copy files with extension "`pub`" containing public SSH keys for your device.
Then run the script: Then run the script:
/ system script run ssh-keys-import; /system/script/run ssh-keys-import;
Starting with an `authorized_keys` file you can split it on a shell: Starting with an `authorized_keys` file you can split it on a shell:

View file

@ -22,7 +22,7 @@ Usage and invocation
Just run the script to play: Just run the script to play:
/ system script run super-mario-theme; /system/script/run super-mario-theme;
For extra fun use it for dhcp lease script. :) For extra fun use it for dhcp lease script. :)

View file

@ -32,7 +32,7 @@ Usage and invocation
Run the script if an upgrade for your LTE hardware is available: Run the script if an upgrade for your LTE hardware is available:
/ system script run unattended-lte-firmware-upgrade; /system/script/run unattended-lte-firmware-upgrade;
Then be patient, go for a coffee and wait for the upgrade process to finish. Then be patient, go for a coffee and wait for the upgrade process to finish.

View file

@ -26,7 +26,7 @@ Just install the script:
... and add a scheduler to run the script periodically: ... and add a scheduler to run the script periodically:
/ system scheduler add interval=30s name=update-gre-address on-event="/ system script run update-gre-address;" start-time=startup; /system/scheduler/add interval=30s name=update-gre-address on-event="/system/script/run update-gre-address;" start-time=startup;
Configuration Configuration
------------- -------------
@ -34,7 +34,7 @@ Configuration
The configuration goes to interface's comment. Add the client's IKEv2 The configuration goes to interface's comment. Add the client's IKEv2
certificate CN into the comment: certificate CN into the comment:
/ interface gre set comment="ikev2-client1" gre-client1; /interface/gre/set comment="ikev2-client1" gre-client1;
--- ---
[◀ Go back to main README](../README.md) [◀ Go back to main README](../README.md)

View file

@ -28,11 +28,11 @@ Configuration
The configuration goes to interface's comment: The configuration goes to interface's comment:
/ interface 6to4 set comment="tunnelbroker, user=user, pass=s3cr3t, id=12345" tunnelbroker; /interface/6to4/set comment="tunnelbroker, user=user, pass=s3cr3t, id=12345" tunnelbroker;
Also enabling dynamic DNS in Mikrotik cloud is required: Also enabling dynamic DNS in Mikrotik cloud is required:
/ ip cloud set ddns-enabled=yes; /ip/cloud/set ddns-enabled=yes;
See also See also
-------- --------

View file

@ -13,7 +13,7 @@
:global LogPrintExit2; :global LogPrintExit2;
:global VersionToNum; :global VersionToNum;
:local RouterBoard [ / system routerboard get ]; :local RouterBoard [ /system/routerboard/get ];
:if ($RouterBoard->"current-firmware" = $RouterBoard->"upgrade-firmware") do={ :if ($RouterBoard->"current-firmware" = $RouterBoard->"upgrade-firmware") do={
$LogPrintExit2 info $0 ("Firmware is already up to date.") true; $LogPrintExit2 info $0 ("Firmware is already up to date.") true;
} }
@ -21,21 +21,21 @@
$LogPrintExit2 info $0 ("Different firmware version is available, but it is a downgrade. Ignoring.") true; $LogPrintExit2 info $0 ("Different firmware version is available, but it is a downgrade. Ignoring.") true;
} }
:if ([ / system routerboard settings get auto-upgrade ] = false) do={ :if ([ /system/routerboard/settings/get auto-upgrade ] = false) do={
$LogPrintExit2 info $0 ("Firmware version " . $RouterBoard->"upgrade-firmware" . \ $LogPrintExit2 info $0 ("Firmware version " . $RouterBoard->"upgrade-firmware" . \
" is available, upgrading.") false; " is available, upgrading.") false;
/ system routerboard upgrade; /system/routerboard/upgrade;
} }
:while ([ :len [ / log find where topics=({"system";"info";"critical"}) \ :while ([ :len [ /log/find where topics=({"system";"info";"critical"}) \
message="Firmware upgraded successfully, please reboot for changes to take effect!" ] ] = 0) do={ message="Firmware upgraded successfully, please reboot for changes to take effect!" ] ] = 0) do={
:delay 1s; :delay 1s;
} }
:local Uptime [ / system resource get uptime ]; :local Uptime [ /system/resource/get uptime ];
:if ($Uptime < 1m) do={ :if ($Uptime < 1m) do={
:delay $Uptime; :delay $Uptime;
} }
$LogPrintExit2 info $0 ("Firmware upgrade successful, rebooting.") false; $LogPrintExit2 info $0 ("Firmware upgrade successful, rebooting.") false;
/ system reboot; /system/reboot;

View file

@ -128,10 +128,10 @@
# Run different commands with multiple mode-button presses. # Run different commands with multiple mode-button presses.
:global ModeButton { :global ModeButton {
1="/ system script run leds-toggle-mode;"; 1="/system/script/run leds-toggle-mode;";
2=":global SendNotification; :global Identity; \$SendNotification (\"Hello...\") (\"Hello world, \" . \$Identity . \" calling!\");"; 2=":global SendNotification; :global Identity; \$SendNotification (\"Hello...\") (\"Hello world, \" . \$Identity . \" calling!\");";
3="/ system shutdown;"; 3="/system/shutdown;";
4="/ system reboot;"; 4="/system/reboot;";
5=":global BridgePortVlan; \$BridgePortVlan alt;"; 5=":global BridgePortVlan; \$BridgePortVlan alt;";
# add more here... # add more here...
}; };
@ -141,8 +141,8 @@
# Run commands on SMS action. # Run commands on SMS action.
:global SmsAction { :global SmsAction {
bridge-port-vlan-alt=":global BridgePortVlan; \$BridgePortVlan alt;"; bridge-port-vlan-alt=":global BridgePortVlan; \$BridgePortVlan alt;";
reboot="/ system reboot;"; reboot="/system/reboot;";
shutdown="/ system shutdown;"; shutdown="/system/shutdown;";
# add more here... # add more here...
}; };
@ -194,7 +194,7 @@
# load custom settings from overlay # load custom settings from overlay
# Warning: Do *NOT* copy this code to overlay! # Warning: Do *NOT* copy this code to overlay!
:do { :do {
/ system script run global-config-overlay; /system/script/run global-config-overlay;
} on-error={ } on-error={
:log error ("Loading configuration from overlay failed!"); :log error ("Loading configuration from overlay failed!");
} }

View file

@ -24,7 +24,7 @@
15="New documentation is online! https://git.eworm.de/cgit/routeros-scripts/about/#available-scripts"; 15="New documentation is online! https://git.eworm.de/cgit/routeros-scripts/about/#available-scripts";
16="Happy with RouterOS Scripts and have a GitHub and/or GitLab account? Please star!"; 16="Happy with RouterOS Scripts and have a GitHub and/or GitLab account? Please star!";
17="Introduced script 'early-errors'"; 17="Introduced script 'early-errors'";
18=("Added a simple IP calculation function, try: \$IPCalc " . [ / ip address get ([ find ]->0) address ]); 18=("Added a simple IP calculation function, try: \$IPCalc " . [ /ip/address/get ([ find ]->0) address ]);
19="Commenting scripts with 'ignore', 'base-url=...' and 'url-suffix=...' is honored on update"; 19="Commenting scripts with 'ignore', 'base-url=...' and 'url-suffix=...' is honored on update";
20="Added support for hooks to 'netwatch-notify'"; 20="Added support for hooks to 'netwatch-notify'";
21="Added support for installing patch updates automatically by 'check-routeros-update'"; 21="Added support for installing patch updates automatically by 'check-routeros-update'";
@ -77,13 +77,13 @@
68="Reintroduced 'global-wait' for functions in scheduler."; 68="Reintroduced 'global-wait' for functions in scheduler.";
69="Support hard lower limit for voltage in 'check-health'."; 69="Support hard lower limit for voltage in 'check-health'.";
70="MikroTik started pushing RouterOS v7. Changes are no longer required."; 70="MikroTik started pushing RouterOS v7. Changes are no longer required.";
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"; 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."; 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')."; 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."; 74="Extended 'hotspot-to-wpa', it can now read additional configuration from templates and hotspot users.";
75=("Finally merged the RouterOS v7 code into the main branch. " . [ $IfThenElse ([ $RequiredRouterOS "global-config.changes" "7.0" false ] = true) \ 75=("Finally merged the RouterOS v7 code into the main branch. " . [ $IfThenElse ([ $RequiredRouterOS "global-config.changes" "7.0" false ] = true) \
("You may now drop '\$ScriptUpdatesUrlSuffix' from 'global-config-overlay'.") \ ("You may now drop '\$ScriptUpdatesUrlSuffix' from 'global-config-overlay'.") \
("Still running RouterOS v6, so last reminder to see https://git.eworm.de/cgit/routeros-scripts/about/#changes-for-routeros-v6") ]); ("Still running RouterOS v6, so last reminder to see https://git.eworm.de/cgit/routeros-scripts/about/#requirements") ]);
76="Added an option to suppress notifications on host down with 'netwatch-notify'."; 76="Added an option to suppress notifications on host down with 'netwatch-notify'.";
77="Introduced new script 'firmware-upgrade-reboot'. Handle with care!"; 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."; 78="New documentation is online for notifications via Telegram & Matrix, variable inspection, ip address calculation and running scripts once.";
@ -93,11 +93,11 @@
# Migration steps to be applied on script updates # Migration steps to be applied on script updates
:global GlobalConfigMigration { :global GlobalConfigMigration {
41=":global SendNotification; \$SendNotification (\"Migration mechanism\") (\"Congratulations!\nSuccessfully tested the new migration mechanism.\");"; 41=":global SendNotification; \$SendNotification (\"Migration mechanism\") (\"Congratulations!\nSuccessfully tested the new migration mechanism.\");";
47="/ certificate remove [ find where fingerprint=\"731d3d9cfaa061487a1d71445a42f67df0afca2a6c2d2f98ff7b3ce112b1f568\" or fingerprint=\"25847d668eb4f04fdd40b12b6b0740c567da7d024308eb6c2c96fe41d9de218d\" ];"; 47="/certificate/remove [ find where fingerprint=\"731d3d9cfaa061487a1d71445a42f67df0afca2a6c2d2f98ff7b3ce112b1f568\" or fingerprint=\"25847d668eb4f04fdd40b12b6b0740c567da7d024308eb6c2c96fe41d9de218d\" ];";
52=":global CertificateDownload; :if ([ :len [ / certificate find where fingerprint=\"67add1166b020ae61b8f5fc96813c04c2aa589960796865572a3c7e737613dfd\" or fingerprint=\"96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6\" ] ] < 2) do={ \$CertificateDownload \"R3\"; }; / certificate remove [ find where fingerprint=\"0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739\" ];"; 52=":global CertificateDownload; :if ([ :len [ /certificate/find where fingerprint=\"67add1166b020ae61b8f5fc96813c04c2aa589960796865572a3c7e737613dfd\" or fingerprint=\"96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6\" ] ] < 2) do={ \$CertificateDownload \"R3\"; }; /certificate/remove [ find where fingerprint=\"0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739\" ];";
54=":global ScriptInstallUpdate; :global TelegramTokenId; :global TelegramChatId; :if ([ :len \$TelegramTokenId ] > 0 && [ :len \$TelegramChatId ] > 0) do={ \$ScriptInstallUpdate mod/notification-telegram; }"; 54=":global ScriptInstallUpdate; :global TelegramTokenId; :global TelegramChatId; :if ([ :len \$TelegramTokenId ] > 0 && [ :len \$TelegramChatId ] > 0) do={ \$ScriptInstallUpdate mod/notification-telegram; }";
61="/ system script remove [ find where name~\"^(early-errors|mode-button-(event|scheduler)|script-updates)\\\$\" source~\"^#!rsc by RouterOS\\n\" ];"; 61="/system/script/remove [ find where name~\"^(early-errors|mode-button-(event|scheduler)|script-updates)\\\$\" source~\"^#!rsc by RouterOS\\n\" ];";
66=":global ScriptInstallUpdate; :if ([ :len [ / system script find where name=\"bridge-port-to-default\" ] ] > 0) do={ / system script remove [ find where name~\"^bridge-port-to(-default|ggle)\\\$\" ]; \$ScriptInstallUpdate mod/bridge-port-to; }"; 66=":global ScriptInstallUpdate; :if ([ :len [ /system/script/find where name=\"bridge-port-to-default\" ] ] > 0) do={ /system/script/remove [ find where name~\"^bridge-port-to(-default|ggle)\\\$\" ]; \$ScriptInstallUpdate mod/bridge-port-to; }";
67=":global ScriptInstallUpdate; :global CharacterReplace; :foreach Script in=[ / system script find where name~\"^global-functions.d/\" ] do={ / system script set name=[ \$CharacterReplace [ / system script get \$Script name ] \"global-functions.d/\" \"mod/\" ] \$Script; }; \$ScriptInstallUpdate;"; 67=":global ScriptInstallUpdate; :global CharacterReplace; :foreach Script in=[ /system/script/find where name~\"^global-functions.d/\" ] do={ /system/script/set name=[ \$CharacterReplace [ /system/script/get \$Script name ] \"global-functions.d/\" \"mod/\" ] \$Script; }; \$ScriptInstallUpdate;";
73=":global ScriptInstallUpdate; :global CharacterReplace; :foreach Old,New in={ \"cloud-backup\"=\"backup-cloud\"; \"email-backup\"=\"backup-email\"; \"upload-backup\"=\"backup-upload\" } do={ / system script set name=\$New [ find where name=\$Old ]; :foreach Scheduler in=[ / system scheduler find where on-event~\$Old ] do={ / system scheduler set \$Scheduler name=[ \$CharacterReplace [ get \$Scheduler name ] \$Old \$New ] on-event=[ \$CharacterReplace [ get \$Scheduler on-event ] \$Old \$New ]; }; }; \$ScriptInstallUpdate;"; 73=":global ScriptInstallUpdate; :global CharacterReplace; :foreach Old,New in={ \"cloud-backup\"=\"backup-cloud\"; \"email-backup\"=\"backup-email\"; \"upload-backup\"=\"backup-upload\" } do={ /system/script/set name=\$New [ find where name=\$Old ]; :foreach Scheduler in=[ /system/scheduler/find where on-event~\$Old ] do={ /system/scheduler/set \$Scheduler name=[ \$CharacterReplace [ get \$Scheduler name ] \$Old \$New ] on-event=[ \$CharacterReplace [ get \$Scheduler on-event ] \$Old \$New ]; }; }; \$ScriptInstallUpdate;";
}; };

View file

@ -14,7 +14,7 @@
# global variables not to be changed by user # global variables not to be changed by user
:global GlobalFunctionsReady false; :global GlobalFunctionsReady false;
:global Identity [ / system identity get name ]; :global Identity [ /system/identity/get name ];
# global functions # global functions
:global CertificateAvailable; :global CertificateAvailable;
@ -69,30 +69,30 @@
:global LogPrintExit2; :global LogPrintExit2;
:global ParseKeyValueStore; :global ParseKeyValueStore;
:if ([ / system resource get free-hdd-space ] < 8388608 && \ :if ([ /system/resource/get free-hdd-space ] < 8388608 && \
[ / certificate settings get crl-download ] = true && \ [ /certificate/settings/get crl-download ] = true && \
[ / certificate settings get crl-store ] = "system") do={ [ /certificate/settings/get crl-store ] = "system") do={
$LogPrintExit2 warning $0 ("This system has low free flash space but " . \ $LogPrintExit2 warning $0 ("This system has low free flash space but " . \
"is configured to download certificate CRLs to system!") false; "is configured to download certificate CRLs to system!") false;
} }
:if ([ :len [ / certificate find where common-name=$CommonName ] ] = 0) do={ :if ([ :len [ /certificate/find where common-name=$CommonName ] ] = 0) do={
$LogPrintExit2 info $0 ("Certificate with CommonName \"" . $CommonName . "\" not available.") false; $LogPrintExit2 info $0 ("Certificate with CommonName \"" . $CommonName . "\" not available.") false;
:if ([ $CertificateDownload $CommonName ] = false) do={ :if ([ $CertificateDownload $CommonName ] = false) do={
:return false; :return false;
} }
} }
:local CertVal [ / certificate get [ find where common-name=$CommonName ] ]; :local CertVal [ /certificate/get [ find where common-name=$CommonName ] ];
:while (($CertVal->"akid") != "" && ($CertVal->"akid") != ($CertVal->"skid")) do={ :while (($CertVal->"akid") != "" && ($CertVal->"akid") != ($CertVal->"skid")) do={
:if ([ :len [ / certificate find where skid=($CertVal->"akid") ] ] = 0) do={ :if ([ :len [ /certificate/find where skid=($CertVal->"akid") ] ] = 0) do={
$LogPrintExit2 info $0 ("Certificate chain for \"" . $CommonName . \ $LogPrintExit2 info $0 ("Certificate chain for \"" . $CommonName . \
"\" is incomplete, missing \"" . ([ $ParseKeyValueStore ($CertVal->"issuer") ]->"CN") . "\".") false; "\" is incomplete, missing \"" . ([ $ParseKeyValueStore ($CertVal->"issuer") ]->"CN") . "\".") false;
:if ([ $CertificateDownload $CommonName ] = false) do={ :if ([ $CertificateDownload $CommonName ] = false) do={
:return false; :return false;
} }
} }
:set CertVal [ / certificate get [ find where skid=($CertVal->"akid") ] ]; :set CertVal [ /certificate/get [ find where skid=($CertVal->"akid") ] ];
} }
:return true; :return true;
} }
@ -114,16 +114,16 @@
:do { :do {
:local LocalFileName ($CommonName . ".pem"); :local LocalFileName ($CommonName . ".pem");
:local UrlFileName ([ $UrlEncode $CommonName ] . ".pem"); :local UrlFileName ([ $UrlEncode $CommonName ] . ".pem");
/ tool fetch check-certificate=yes-without-crl \ /tool/fetch check-certificate=yes-without-crl \
($ScriptUpdatesBaseUrl . "certs/" . \ ($ScriptUpdatesBaseUrl . "certs/" . \
$UrlFileName . $ScriptUpdatesUrlSuffix) \ $UrlFileName . $ScriptUpdatesUrlSuffix) \
dst-path=$LocalFileName as-value; dst-path=$LocalFileName as-value;
$WaitForFile $LocalFileName; $WaitForFile $LocalFileName;
/ certificate import file-name=$LocalFileName passphrase="" as-value; /certificate/import file-name=$LocalFileName passphrase="" as-value;
/ file remove $LocalFileName; /file/remove $LocalFileName;
:foreach Cert in=[ / certificate find where name~("^" . $LocalFileName . "_[0-9]+\$") ] do={ :foreach Cert in=[ /certificate/find where name~("^" . $LocalFileName . "_[0-9]+\$") ] do={
$CertificateNameByCN [ / certificate get $Cert common-name ]; $CertificateNameByCN [ /certificate/get $Cert common-name ];
} }
} on-error={ } on-error={
$LogPrintExit2 warning $0 ("Failed importing certificate with " . \ $LogPrintExit2 warning $0 ("Failed importing certificate with " . \
@ -139,8 +139,8 @@
:global CharacterReplace; :global CharacterReplace;
:local Cert [ / certificate find where common-name=$CommonName ]; :local Cert [ /certificate/find where common-name=$CommonName ];
/ certificate set $Cert \ /certificate/set $Cert \
name=[ $CharacterReplace [ $CharacterReplace [ $CharacterReplace $CommonName "'" "-" ] " " "-" ] "---" "-" ]; name=[ $CharacterReplace [ $CharacterReplace [ $CharacterReplace $CommonName "'" "-" ] " " "-" ] "---" "-" ];
} }
@ -185,7 +185,7 @@
# default route is reachable # default route is reachable
:set DefaultRouteIsReachable do={ :set DefaultRouteIsReachable do={
:if ([ :len [ / ip route find where dst-address=0.0.0.0/0 active routing-table=main ] ] > 0) do={ :if ([ :len [ /ip/route/find where dst-address=0.0.0.0/0 active routing-table=main ] ] > 0) do={
:return true; :return true;
} }
:return false; :return false;
@ -199,13 +199,13 @@
:global IfThenElse; :global IfThenElse;
:local Resource [ / system resource get ]; :local Resource [ /system/resource/get ];
:local RouterBoard; :local RouterBoard;
:do { :do {
:set RouterBoard [ / system routerboard get ]; :set RouterBoard [[ :parse "/system/routerboard/get" ]];
} on-error={ } } on-error={ }
:local License [ / system license get ]; :local License [ /system/license/get ];
:local Update [ / system package update get ]; :local Update [ /system/package/update/get ];
:return ( \ :return ( \
"Hostname: " . $Identity . \ "Hostname: " . $Identity . \
@ -259,8 +259,8 @@
:global WaitForFile; :global WaitForFile;
:if ([ :len $PkgName ] = 0) do={ :return false; } :if ([ :len $PkgName ] = 0) do={ :return false; }
:if ([ :len $PkgVer ] = 0) do={ :set PkgVer [ / system package update get installed-version ]; } :if ([ :len $PkgVer ] = 0) do={ :set PkgVer [ /system/package/update/get installed-version ]; }
:if ([ :len $PkgArch ] = 0) do={ :set PkgArch [ / system resource get architecture-name ]; } :if ([ :len $PkgArch ] = 0) do={ :set PkgArch [ /system/resource/get architecture-name ]; }
:if ($PkgName = "system") do={ :set PkgName "routeros"; } :if ($PkgName = "system") do={ :set PkgName "routeros"; }
@ -273,7 +273,7 @@
:return false; :return false;
} }
:if ([ :len [ / file find where name=$PkgDest type="package" ] ] > 0) do={ :if ([ :len [ /file/find where name=$PkgDest type="package" ] ] > 0) do={
$LogPrintExit2 info $0 ("Package file " . $PkgName . " already exists.") false; $LogPrintExit2 info $0 ("Package file " . $PkgName . " already exists.") false;
:return true; :return true;
} }
@ -288,17 +288,17 @@
:local Retry 3; :local Retry 3;
:while ($Retry > 0) do={ :while ($Retry > 0) do={
:do { :do {
/ tool fetch check-certificate=yes-without-crl $Url dst-path=$PkgDest; /tool/fetch check-certificate=yes-without-crl $Url dst-path=$PkgDest;
$WaitForFile $PkgDest; $WaitForFile $PkgDest;
:if ([ / file get [ find where name=$PkgDest ] type ] = "package") do={ :if ([ /file/get [ find where name=$PkgDest ] type ] = "package") do={
:return true; :return true;
} }
} on-error={ } on-error={
$LogPrintExit2 debug $0 ("Downloading package file failed.") false; $LogPrintExit2 debug $0 ("Downloading package file failed.") false;
} }
/ file remove [ find where name=$PkgDest ]; /file/remove [ find where name=$PkgDest ];
:set Retry ($Retry - 1); :set Retry ($Retry - 1);
} }
@ -348,28 +348,28 @@
:local AllDone true; :local AllDone true;
:local QueueLen [ :len $EmailQueue ]; :local QueueLen [ :len $EmailQueue ];
:if ([ :len [ / system scheduler find where name="FlushEmailQueue" ] ] > 0 && $QueueLen = 0) do={ :if ([ :len [ /system/scheduler/find where name="FlushEmailQueue" ] ] > 0 && $QueueLen = 0) do={
$LogPrintExit2 warning $0 ("Flushing E-Mail messages from scheduler, but queue is empty.") false; $LogPrintExit2 warning $0 ("Flushing E-Mail messages from scheduler, but queue is empty.") false;
} }
/ system scheduler set interval=($QueueLen . "m") [ find where name="FlushEmailQueue" ]; /system/scheduler/set interval=($QueueLen . "m") [ find where name="FlushEmailQueue" ];
:foreach Id,Message in=$EmailQueue do={ :foreach Id,Message in=$EmailQueue do={
:if ([ :typeof $Message ] = "array" ) do={ :if ([ :typeof $Message ] = "array" ) do={
:local Attach [ $EitherOr ($Message->"attach") "" ]; :local Attach [ $EitherOr ($Message->"attach") "" ];
:while ([ / tool e-mail get last-status ] = "in-progress") do={ :delay 1s; } :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") \ /tool/e-mail/send to=($Message->"to") cc=($Message->"cc") subject=($Message->"subject") \
body=($Message->"body") file=$Attach; body=($Message->"body") file=$Attach;
:local Wait true; :local Wait true;
:do { :do {
:delay 1s; :delay 1s;
:local Status [ / tool e-mail get last-status ]; :local Status [ /tool/e-mail/get last-status ];
:if ($Status = "succeeded") do={ :if ($Status = "succeeded") do={
:set ($EmailQueue->$Id); :set ($EmailQueue->$Id);
:set Wait false; :set Wait false;
:if (($Message->"remove-attach") = true) do={ :if (($Message->"remove-attach") = true) do={
:foreach File in=[ :toarray $Attach ] do={ :foreach File in=[ :toarray $Attach ] do={
/ file remove $File; /file/remove $File;
} }
} }
} }
@ -382,10 +382,10 @@
} }
:if ($AllDone = true && $QueueLen = [ :len $EmailQueue ]) do={ :if ($AllDone = true && $QueueLen = [ :len $EmailQueue ]) do={
/ system scheduler remove [ find where name="FlushEmailQueue" ]; /system/scheduler/remove [ find where name="FlushEmailQueue" ];
:set EmailQueue; :set EmailQueue;
} else={ } else={
/ system scheduler set interval=1m [ find where name="FlushEmailQueue" ]; /system/scheduler/set interval=1m [ find where name="FlushEmailQueue" ];
} }
} }
@ -400,12 +400,12 @@
:if ([ $CertificateAvailable "Cloudflare Inc ECC CA-3" ] = false) do={ :if ([ $CertificateAvailable "Cloudflare Inc ECC CA-3" ] = false) do={
$LogPrintExit2 warning $0 ("Downloading required certificate failed.") true; $LogPrintExit2 warning $0 ("Downloading required certificate failed.") true;
} }
:local Vendor ([ / tool fetch check-certificate=yes-without-crl \ :local Vendor ([ /tool/fetch check-certificate=yes-without-crl \
("https://api.macvendors.com/" . [ :pick $Mac 0 8 ]) output=user as-value ]->"data"); ("https://api.macvendors.com/" . [ :pick $Mac 0 8 ]) output=user as-value ]->"data");
:return $Vendor; :return $Vendor;
} on-error={ } on-error={
:do { :do {
/ tool fetch check-certificate=yes-without-crl ("https://api.macvendors.com/") \ /tool/fetch check-certificate=yes-without-crl ("https://api.macvendors.com/") \
output=none as-value; output=none as-value;
$LogPrintExit2 debug $0 ("The mac vendor is not known in database.") false; $LogPrintExit2 debug $0 ("The mac vendor is not known in database.") false;
} on-error={ } on-error={
@ -417,7 +417,7 @@
# generate random 20 chars hex (0-9 and a-f) # generate random 20 chars hex (0-9 and a-f)
:set GetRandom20CharHex do={ :set GetRandom20CharHex do={
:return ([ / certificate scep-server otp generate minutes-valid=0 as-value ]->"password"); :return ([ /certificate/scep-server/otp/generate minutes-valid=0 as-value ]->"password");
} }
# generate random number # generate random number
@ -515,20 +515,20 @@
:return true; :return true;
} }
:if ([ :len [ / file find where name=$Dir type="directory" ] ] = 1) do={ :if ([ :len [ /file/find where name=$Dir type="directory" ] ] = 1) do={
:return true; :return true;
} }
:local Return true; :local Return true;
:local Name ($Dir . "-" . [ $GetRandom20CharHex ]); :local Name ($Dir . "-" . [ $GetRandom20CharHex ]);
:do { :do {
/ ip smb share add disabled=yes directory=$Dir name=$Name; /ip/smb/share/add disabled=yes directory=$Dir name=$Name;
$WaitForFile $Dir; $WaitForFile $Dir;
} on-error={ } on-error={
$LogPrintExit2 warning $0 ("Making directory '" . $Dir . "' failed!") false; $LogPrintExit2 warning $0 ("Making directory '" . $Dir . "' failed!") false;
:set Return false; :set Return false;
} }
/ ip smb share remove [ find where name=$Name ]; /ip/smb/share/remove [ find where name=$Name ];
:return $Return; :return $Return;
} }
@ -555,7 +555,7 @@
:local To [ $EitherOr ($EmailGeneralToOverride->($Notification->"origin")) $EmailGeneralTo ]; :local To [ $EitherOr ($EmailGeneralToOverride->($Notification->"origin")) $EmailGeneralTo ];
:local Cc [ $EitherOr ($EmailGeneralCcOverride->($Notification->"origin")) $EmailGeneralCc ]; :local Cc [ $EitherOr ($EmailGeneralCcOverride->($Notification->"origin")) $EmailGeneralCc ];
:local EMailSettings [ / tool e-mail get ]; :local EMailSettings [ /tool/e-mail/get ];
:if ([ :len $To ] = 0 || ($EMailSettings->"address") = "0.0.0.0" || ($EMailSettings->"from") = "<>") do={ :if ([ :len $To ] = 0 || ($EMailSettings->"address") = "0.0.0.0" || ($EMailSettings->"from") = "<>") do={
:return false; :return false;
} }
@ -563,7 +563,7 @@
:if ([ :typeof $EmailQueue ] = "nothing") do={ :if ([ :typeof $EmailQueue ] = "nothing") do={
:set EmailQueue [ :toarray "" ]; :set EmailQueue [ :toarray "" ];
} }
:local Signature [ / system note get note ]; :local Signature [ /system/note/get note ];
:set ($EmailQueue->[ :len $EmailQueue ]) { :set ($EmailQueue->[ :len $EmailQueue ]) {
to=$To; cc=$Cc; to=$To; cc=$Cc;
subject=[ $QuotedPrintable ("[" . $Identity . "] " . ($Notification->"subject")) ]; subject=[ $QuotedPrintable ("[" . $Identity . "] " . ($Notification->"subject")) ];
@ -571,8 +571,8 @@
[ $IfThenElse ([ :len ($Notification->"link") ] > 0) ("\n\n" . ($Notification->"link")) "" ] . \ [ $IfThenElse ([ :len ($Notification->"link") ] > 0) ("\n\n" . ($Notification->"link")) "" ] . \
[ $IfThenElse ([ :len $Signature ] > 0) ("\n-- \n" . $Signature) "" ]); \ [ $IfThenElse ([ :len $Signature ] > 0) ("\n-- \n" . $Signature) "" ]); \
attach=($Notification->"attach"); remove-attach=($Notification->"remove-attach") }; attach=($Notification->"attach"); remove-attach=($Notification->"remove-attach") };
:if ([ :len [ / system scheduler find where name="FlushEmailQueue" ] ] = 0) do={ :if ([ :len [ /system/scheduler/find where name="FlushEmailQueue" ] ] = 0) do={
/ system scheduler add name=FlushEmailQueue interval=1s start-time=startup \ /system/scheduler/add name=FlushEmailQueue interval=1s start-time=startup \
on-event=(":global FlushEmailQueue; \$FlushEmailQueue;"); on-event=(":global FlushEmailQueue; \$FlushEmailQueue;");
} }
} }
@ -653,7 +653,7 @@
:global IfThenElse; :global IfThenElse;
:global LogPrintExit2; :global LogPrintExit2;
:global VersionToNum; :global VersionToNum;
:if ([ $VersionToNum $Required ] > [ $VersionToNum [ / system package update get installed-version ] ]) do={ :if ([ $VersionToNum $Required ] > [ $VersionToNum [ /system/package/update/get installed-version ] ]) do={
:if ($Warn = "true") do={ :if ($Warn = "true") do={
$LogPrintExit2 warning $0 ("This " . [ $IfThenElse ([ :pick $Caller 0 ] = ("\$")) "function" "script" ] . \ $LogPrintExit2 warning $0 ("This " . [ $IfThenElse ([ :pick $Caller 0 ] = ("\$")) "function" "script" ] . \
" '" . $Caller . "' (at least specific functionality) requires RouterOS " . $Required . ". Please update!") false; " '" . $Caller . "' (at least specific functionality) requires RouterOS " . $Required . ". Please update!") false;
@ -669,10 +669,10 @@
:global LogPrintExit2; :global LogPrintExit2;
:foreach Job in=[ / system script job find where script=$Script ] do={ :foreach Job in=[ /system/script/job/find where script=$Script ] do={
:set Job [ / system script job get $Job ]; :set Job [ /system/script/job/get $Job ];
:while ([ :typeof ($Job->"parent") ] = "id") do={ :while ([ :typeof ($Job->"parent") ] = "id") do={
:set Job [ / system script job get [ find where .id=($Job->"parent") ] ]; :set Job [ /system/script/job/get [ find where .id=($Job->"parent") ] ];
} }
:if (($Job->"type") = "login") do={ :if (($Job->"type") = "login") do={
$LogPrintExit2 debug $0 ("Script " . $Script . " started from terminal.") false; $LogPrintExit2 debug $0 ("Script " . $Script . " started from terminal.") false;
@ -712,9 +712,9 @@
} }
:foreach Script in=$Scripts do={ :foreach Script in=$Scripts do={
:if ([ :len [ / system script find where name=$Script ] ] = 0) do={ :if ([ :len [ /system/script/find where name=$Script ] ] = 0) do={
$LogPrintExit2 info $0 ("Adding new script: " . $Script) false; $LogPrintExit2 info $0 ("Adding new script: " . $Script) false;
/ system script add name=$Script owner=$Script source="#!rsc by RouterOS\n" comment=$NewComment; /system/script/add name=$Script owner=$Script source="#!rsc by RouterOS\n" comment=$NewComment;
} }
} }
@ -722,17 +722,17 @@
:local ReloadGlobalFunctions false; :local ReloadGlobalFunctions false;
:local ReloadGlobalConfig false; :local ReloadGlobalConfig false;
:foreach Script in=[ / system script find where source~"^#!rsc by RouterOS\n" ] do={ :foreach Script in=[ /system/script/find where source~"^#!rsc by RouterOS\n" ] do={
:local ScriptVal [ / system script get $Script ]; :local ScriptVal [ /system/script/get $Script ];
:local ScriptFile [ / file find where name=("script-updates/" . $ScriptVal->"name") ]; :local ScriptFile [ /file/find where name=("script-updates/" . $ScriptVal->"name") ];
:local SourceNew; :local SourceNew;
:if ([ :len $ScriptFile ] > 0) do={ :if ([ :len $ScriptFile ] > 0) do={
:set SourceNew [ / file get $ScriptFile content ]; :set SourceNew [ /file/get $ScriptFile content ];
/ file remove $ScriptFile; /file/remove $ScriptFile;
} }
:foreach Scheduler in=[ / system scheduler find where on-event~("\\b" . $ScriptVal->"name" . "\\b") ] do={ :foreach Scheduler in=[ /system/scheduler/find where on-event~("\\b" . $ScriptVal->"name" . "\\b") ] do={
:local SchedulerVal [ / system scheduler get $Scheduler ]; :local SchedulerVal [ /system/scheduler/get $Scheduler ];
:if ($ScriptVal->"policy" != $SchedulerVal->"policy") do={ :if ($ScriptVal->"policy" != $SchedulerVal->"policy") do={
$LogPrintExit2 warning $0 ("Policies differ for script '" . $ScriptVal->"name" . \ $LogPrintExit2 warning $0 ("Policies differ for script '" . $ScriptVal->"name" . \
"' and its scheduler '" . $SchedulerVal->"name" . "'!") false; "' and its scheduler '" . $SchedulerVal->"name" . "'!") false;
@ -750,7 +750,7 @@
:local Url ($BaseUrl . $ScriptVal->"name" . $UrlSuffix); :local Url ($BaseUrl . $ScriptVal->"name" . $UrlSuffix);
$LogPrintExit2 debug $0 ("Fetching script '" . $ScriptVal->"name" . "' from url: " . $Url) false; $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 ]; :local Result [ /tool/fetch check-certificate=yes-without-crl $Url output=user as-value ];
:if ($Result->"status" = "finished") do={ :if ($Result->"status" = "finished") do={
:set SourceNew ($Result->"data"); :set SourceNew ($Result->"data");
} }
@ -767,7 +767,7 @@
:local DontRequirePermissions \ :local DontRequirePermissions \
($SourceNew~"\n# requires: dont-require-permissions=yes\n"); ($SourceNew~"\n# requires: dont-require-permissions=yes\n");
$LogPrintExit2 info $0 ("Updating script: " . $ScriptVal->"name") false; $LogPrintExit2 info $0 ("Updating script: " . $ScriptVal->"name") false;
/ system script set owner=($ScriptVal->"name") source=$SourceNew \ /system/script/set owner=($ScriptVal->"name") source=$SourceNew \
dont-require-permissions=$DontRequirePermissions $Script; dont-require-permissions=$DontRequirePermissions $Script;
:if ($ScriptVal->"name" = "global-config") do={ :if ($ScriptVal->"name" = "global-config") do={
:set ReloadGlobalConfig true; :set ReloadGlobalConfig true;
@ -794,7 +794,7 @@
:if ($ReloadGlobalFunctions = true) do={ :if ($ReloadGlobalFunctions = true) do={
$LogPrintExit2 info $0 ("Reloading global functions.") false; $LogPrintExit2 info $0 ("Reloading global functions.") false;
:do { :do {
/ system script run global-functions; /system/script/run global-functions;
} on-error={ } on-error={
$LogPrintExit2 error $0 ("Reloading global functions failed!") false; $LogPrintExit2 error $0 ("Reloading global functions failed!") false;
} }
@ -803,7 +803,7 @@
:if ($ReloadGlobalConfig = true) do={ :if ($ReloadGlobalConfig = true) do={
$LogPrintExit2 info $0 ("Reloading global configuration.") false; $LogPrintExit2 info $0 ("Reloading global configuration.") false;
:do { :do {
/ system script run global-config; /system/script/run global-config;
} on-error={ } on-error={
$LogPrintExit2 error $0 ("Reloading global configuration failed!" . \ $LogPrintExit2 error $0 ("Reloading global configuration failed!" . \
" Syntax error or missing overlay\?") false; " Syntax error or missing overlay\?") false;
@ -818,7 +818,7 @@
:do { :do {
:local Url ($ScriptUpdatesBaseUrl . "global-config.changes" . $ScriptUpdatesUrlSuffix); :local Url ($ScriptUpdatesBaseUrl . "global-config.changes" . $ScriptUpdatesUrlSuffix);
$LogPrintExit2 debug $0 ("Fetching news, changes and migration: " . $Url) false; $LogPrintExit2 debug $0 ("Fetching news, changes and migration: " . $Url) false;
:local Result [ / tool fetch check-certificate=yes-without-crl $Url output=user as-value ]; :local Result [ /tool/fetch check-certificate=yes-without-crl $Url output=user as-value ];
:if ($Result->"status" = "finished") do={ :if ($Result->"status" = "finished") do={
:set ChangeLogCode ($Result->"data"); :set ChangeLogCode ($Result->"data");
} }
@ -918,7 +918,7 @@
:local JobCount do={ :local JobCount do={
:local Script [ :tostr $1 ]; :local Script [ :tostr $1 ];
:return [ :len [ / system script job find where script=$Script ] ]; :return [ :len [ /system/script/job/find where script=$Script ] ];
} }
:local TicketCount do={ :local TicketCount do={
@ -990,7 +990,7 @@
:set ($ScriptLockOrder->$Script) [ :toarray "" ]; :set ($ScriptLockOrder->$Script) [ :toarray "" ];
} }
:if ([ :len [ / system script find where name=$Script ] ] = 0) do={ :if ([ :len [ /system/script/find where name=$Script ] ] = 0) do={
$LogPrintExit2 error $0 ("A script named '" . $Script . "' does not exist!") true; $LogPrintExit2 error $0 ("A script named '" . $Script . "' does not exist!") true;
} }
@ -1001,7 +1001,7 @@
:if ([ $TicketCount $Script ] >= [ $JobCount $Script ]) do={ :if ([ $TicketCount $Script ] >= [ $JobCount $Script ]) do={
$LogPrintExit2 error $0 ("More tickets than running scripts '" . $Script . "', resetting!") false; $LogPrintExit2 error $0 ("More tickets than running scripts '" . $Script . "', resetting!") false;
:set ($ScriptLockOrder->$Script) [ :toarray "" ]; :set ($ScriptLockOrder->$Script) [ :toarray "" ];
/ system script job remove [ find where script=$Script ]; /system/script/job/remove [ find where script=$Script ];
} }
:local MyTicket [ $GetRandom20CharHex ]; :local MyTicket [ $GetRandom20CharHex ];
@ -1107,21 +1107,21 @@
:set TimeIsSync do={ :set TimeIsSync do={
:global LogPrintExit2; :global LogPrintExit2;
:if ([ / system ntp client get enabled ] = true) do={ :if ([ /system/ntp/client/get enabled ] = true) do={
:do { :do {
:if ([ / system ntp client get status ] = "synchronized") do={ :if ([ /system/ntp/client/get status ] = "synchronized") do={
:return true; :return true;
} }
} on-error={ } on-error={
:if ([ :typeof [ / system ntp client get last-adjustment ] ] = "time") do={ :if ([ :typeof [ /system/ntp/client/get last-adjustment ] ] = "time") do={
:return true; :return true;
} }
} }
:return false; :return false;
} }
:if ([ / ip cloud get ddns-enabled ] = true && [ / ip cloud get update-time ] = true) do={ :if ([ /ip/cloud/get ddns-enabled ] = true && [ /ip/cloud/get update-time ] = true) do={
:if ([ :typeof [ / ip cloud get public-address ] ] = "ip") do={ :if ([ :typeof [ /ip/cloud/get public-address ] ] = "ip") do={
:return true; :return true;
} }
:return false; :return false;
@ -1226,7 +1226,7 @@
:set FileName [ $CleanFilePath $FileName ]; :set FileName [ $CleanFilePath $FileName ];
:local I 0; :local I 0;
:while ([ :len [ / file find where name=$FileName ] ] = 0) do={ :while ([ :len [ /file/find where name=$FileName ] ] = 0) do={
:if ($I > 20) do={ :if ($I > 20) do={
:return false; :return false;
} }
@ -1253,10 +1253,10 @@
:global TimeIsSync; :global TimeIsSync;
:while ([ $TimeIsSync ] = false) do={ :while ([ $TimeIsSync ] = false) do={
:if ([ :len [ / system script find where name="rotate-ntp" ] ] > 0 && \ :if ([ :len [ /system/script/find where name="rotate-ntp" ] ] > 0 && \
([ / system resource get uptime ] % (180 * 1000000000)) = 0s) do={ ([ /system/resource/get uptime ] % (180 * 1000000000)) = 0s) do={
:do { :do {
/ system script run rotate-ntp; /system/script/run rotate-ntp;
} on-error={ } on-error={
$LogPrintExit2 debug $0 ("Running rotate-ntp failed.") false; $LogPrintExit2 debug $0 ("Running rotate-ntp failed.") false;
} }
@ -1266,11 +1266,11 @@
} }
# load modules # load modules
:foreach Script in=[ / system script find where name ~ "^mod/." ] do={ :foreach Script in=[ /system/script/find where name ~ "^mod/." ] do={
:local ScriptVal [ / system script get $Script ]; :local ScriptVal [ /system/script/get $Script ];
:if ([ $ValidateSyntax ($ScriptVal->"source") ] = true) do={ :if ([ $ValidateSyntax ($ScriptVal->"source") ] = true) do={
:do { :do {
/ system script run $Script; /system/script/run $Script;
} on-error={ } on-error={
$LogPrintExit2 error $0 ("Module '" . $ScriptVal->"name" . "' failed to run.") false; $LogPrintExit2 error $0 ("Module '" . $ScriptVal->"name" . "' failed to run.") false;
} }
@ -1280,12 +1280,7 @@
} }
# check for required RouterOS version # check for required RouterOS version
:if ([ $RequiredRouterOS $0 "7.0" false ] = true) do={ $RequiredRouterOS $0 "7.1" true;
$RequiredRouterOS $0 "7.1" true;
} else={
$LogPrintExit2 warning $0 ("Still running RouterOS v6, please switch to branch " . \
"'routeros-v6', see https://git.eworm.de/cgit/routeros-scripts/about/#changes-for-routeros-v6") false;
}
# signal we are ready # signal we are ready
:set GlobalFunctionsReady true; :set GlobalFunctionsReady true;

View file

@ -15,11 +15,11 @@
:global LogPrintExit2; :global LogPrintExit2;
:local CoordinateFormat [ / system gps get coordinate-format ]; :local CoordinateFormat [ /system/gps/get coordinate-format ];
:local Gps [ / system gps monitor once as-value ]; :local Gps [ /system/gps/monitor once as-value ];
:if ($Gps->"valid" = true) do={ :if ($Gps->"valid" = true) do={
/ tool fetch check-certificate=yes-without-crl $GpsTrackUrl output=none \ /tool/fetch check-certificate=yes-without-crl $GpsTrackUrl output=none \
http-method=post http-header-field="Content-Type: application/json" \ http-method=post http-header-field="Content-Type: application/json" \
http-data=("{" . \ http-data=("{" . \
"\"lat\":\"" . ($Gps->"latitude") . "\"," . \ "\"lat\":\"" . ($Gps->"latitude") . "\"," . \

Some files were not shown because too many files have changed in this diff Show more