Compare commits

...

243 commits

Author SHA1 Message Date
Christian Hesse 44fc69e82d packages-update: drop RouterOS version check...
... and allow all updates again. This requires RouterOS 7.13.
2024-03-12 21:39:38 +01:00
Christian Hesse b829ec1fc9 mod/ssh-keys-import: do not exit with error 2024-03-12 20:37:57 +01:00
Christian Hesse 0e2e7efdb2 mod/scriptrunonce: do not exit with error 2024-03-12 20:37:57 +01:00
Christian Hesse c2dc8a0837 mod/notification-matrix: do not exit with error 2024-03-12 20:37:57 +01:00
Christian Hesse 525e4325da mod/bridge-port-vlan: do not exit with error 2024-03-12 20:37:57 +01:00
Christian Hesse 39dd1f2a63 mod/bridge-port-to: do not exit with error 2024-03-12 20:37:57 +01:00
Christian Hesse ba2df80f07 Merge branch 'LogPrint' into next 2024-03-12 20:37:57 +01:00
Christian Hesse 19802c0b69 global-functions: $LogPrintOnce: drop support for exit
This is not widely adopted or used, so let's just drop it - no
compatibility.
2024-03-12 20:37:57 +01:00
Christian Hesse 242ecef012 update-tunnelbroker: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 76f65c13d7 global-functions: add architecture in user-agent string 2024-03-12 20:37:57 +01:00
Christian Hesse 9a21f4d3e3 update-gre-address: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 1c61547284 global-config: merge loading overlay and snippets 2024-03-12 20:37:57 +01:00
Christian Hesse 19fb5c5801 telegram-chat: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse be1aeccbe5 sms-forward: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 5a487d15c2 sms-action: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 88d4c0aff8 ppp-on-up: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 8444e5f270 packages-update: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse ad65b62c1c ospf-to-leds: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 030105cc2e netwatch-notify: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 8ea24540c4 netwatch-dns: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse e3d55819ee mode-button: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse eedf092930 mod/ssh-keys-import: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 8c62c31604 mod/scriptrunonce: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 699f09c282 mod/notification-telegram: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse fb88521ed5 mod/notification-ntfy: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 279993e965 mod/notification-matrix: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 9b8d3f7970 mod/notification-email: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse bdcf43a6f6 mod/bridge-port-vlan: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse b7983d18c4 mod/bridge-port-to: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse f8c79abd38 log-forward: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 29a72e54dc lease-script: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 1f938efcaf ipv6-update: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 56e39123b9 ipsec-to-dns: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 369af47374 hotspot-to-wpa: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse d93ffb9cb2 hotspot-to-wpa-cleanup: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 5c567604ff gps-track: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 9dd1b768ee global-functions: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 6715696ba1 fw-addr-lists: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse c8e4cb0526 firmware-upgrade-reboot: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 5c775fdb3f dhcp-to-dns: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 5638bdcc2d dhcp-lease-comment: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 4ab8dbd774 daily-psk: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 5016f4d28c collect-wireless-mac: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse a996bdac2a check-routeros-update: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 7f154a178b check-lte-firmware-upgrade: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 463393647f check-health: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 3625808749 check-certificates: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 7c38b9a35c certificate-renew-issued: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 12435ff1c5 capsman-rolling-upgrade: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse e40da1e7e4 capsman-download-packages: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse ca822e1358 backup-upload: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse b879f8fef2 backup-partition: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 4b69144ee4 backup-email: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse ac3b755fdc backup-cloud: switch to $LogPrint 2024-03-12 20:37:57 +01:00
Christian Hesse 1feeed145d global-functions: introduce $LogPrint, deprecate $LogPrintExit2 2024-03-12 20:37:57 +01:00
Christian Hesse a7cb3e520a global-config: support loading snippets
This adds support for loading snippets, which need a name starting with
"global-config-overlay.d/". This allows to split off configuration if
desired.
2024-03-12 20:36:21 +01:00
Christian Hesse e39e8a0083 backup-upload: pass failure to packages-update 2024-03-12 15:27:15 +01:00
Christian Hesse 51b00181cf backup-partition: pass failure to packages-update 2024-03-12 15:27:15 +01:00
Christian Hesse 5f41bd1c1e backup-email: pass failure to packages-update 2024-03-12 15:27:15 +01:00
Christian Hesse c82f776632 backup-cloud: pass failure to packages-update 2024-03-12 15:27:15 +01:00
Christian Hesse 3fcdd395fe packages-update: support passing backup failure 2024-03-12 15:27:15 +01:00
Christian Hesse ffa31c7ad7 packages-update: increate log severity on canceled non-interactive update 2024-03-12 15:27:15 +01:00
Christian Hesse 6fd39bd3c5 Merge branch 'do-with-on-error' into next 2024-03-12 15:27:15 +01:00
Christian Hesse b86d631486 doc/telegram-chat: show usage of persistent ids 2024-03-12 15:27:15 +01:00
Christian Hesse f0856c264e update-tunnelbroker: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse a0a2046373 Merge branch 'doc-badges' into next 2024-03-12 15:27:15 +01:00
Christian Hesse febd13af13 update-gre-address: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 09393d3ef5 check-certificates: handle formatting of self signed cert 2024-03-12 15:27:15 +01:00
Christian Hesse 4061661a20 doc/update-tunnelbroker: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 738dd11929 telegram-chat: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 53ff8fbf97 check-certificates: exit block on failed import 2024-03-12 15:27:15 +01:00
Christian Hesse a0a964fa18 doc/update-gre-address: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse ac38e16944 sms-forward: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse a7cd7d9500 Merge branch 'drop-wifiwave2' into next 2024-03-12 15:27:15 +01:00
Christian Hesse 11832a7651 doc/unattended-lte-firmware-upgrade: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse e19a48682e sms-action: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 050ccd490e backup-cloud: add a short delay
Not sure it helps, but chances are...
2024-03-12 15:27:15 +01:00
Christian Hesse 83dbcfecd5 news on wifiwave2 EOL 2024-03-12 15:27:15 +01:00
Christian Hesse 2ac18b1cdf doc/telegram-chat: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 1db1a943e2 ppp-on-up: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 955ee8499b backup-cloud: catch error with :execute workaround
Catching a runtime error here fails... So let's try a workaround
with :execute...
2024-03-12 15:27:15 +01:00
Christian Hesse d513ea61cf hotspot-to-wpa-cleanup: drop support for wifiwave2 2024-03-12 15:27:15 +01:00
Christian Hesse 8a439ea15c doc/super-mario-theme: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 1012d9fc51 packages-update: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 010bea56dc telegram-chat: error when making directory fails 2024-03-12 15:27:15 +01:00
Christian Hesse 0385c032e2 hotspot-to-wpa: drop support for wifiwave2 2024-03-12 15:27:15 +01:00
Christian Hesse 3995e85ccf doc/sms-forward: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 850e8db975 ospf-to-leds: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse ed790dea6e mod/notification-email: remove extra spaces 2024-03-12 15:27:15 +01:00
Christian Hesse 074e70ee51 dhcp-lease-comment: drop support for wifiwave2 2024-03-12 15:27:15 +01:00
Christian Hesse 42d8fed577 doc/sms-action: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 18ed12e3f7 netwatch-notify: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 4e1362aacc mod/inspectvar: remove extra spaces 2024-03-12 15:27:15 +01:00
Christian Hesse decb8fb17a daily-psk: drop support for wifiwave2 2024-03-12 15:27:15 +01:00
Christian Hesse 2038480b00 doc/ppp-on-up: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 8fcb8efbea netwatch-dns: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 0d35a18c71 global-wait: drop unused variable 2024-03-12 15:27:15 +01:00
Christian Hesse b414608329 collect-wireless-mac: drop support for wifiwave2 2024-03-12 15:27:15 +01:00
Christian Hesse 4ff543e629 doc/packages-update: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 4dd6bdef31 mode-button: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse c462c0b598 Merge branch 'no-error-on-exit' into next 2024-03-12 15:27:15 +01:00
Christian Hesse e8c5585cc7 capsman-rolling-upgrade: drop support for wifiwave2 2024-03-12 15:27:15 +01:00
Christian Hesse 6786fbb292 doc/ospf-to-leds: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 52f54baea0 log-forward: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse ada9153636 global-functions: $ScriptLock: fix wording...
... as this does (no longer) abort.
2024-03-12 15:27:15 +01:00
Christian Hesse 34620ba53c capsman-download-packages: drop support for wifiwave2 2024-03-12 15:27:15 +01:00
Christian Hesse cdc0db3b81 doc/netwatch-notify: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 6546e7f085 lease-script: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 1e8918fdaa global-functions: $ScriptLock: do not exit from global function 2024-03-12 15:27:15 +01:00
Christian Hesse 9ecc3c4c49 accesslist-duplicates: drop support for wifiwave2 2024-03-12 15:27:15 +01:00
Christian Hesse fe83328a57 doc/netwatch-dns: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 6f91c97b7f ipv6-update: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 56e97dd60c global-functions: $DownloadPackage: do not exit from global function 2024-03-12 15:27:15 +01:00
Christian Hesse d799edfc17 Makefile: drop support for wifiwave2 2024-03-12 15:27:15 +01:00
Christian Hesse 2170505beb doc/mode-button: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 341e84682c ipsec-to-dns: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 4004d713aa sms-forward: do not exit with error 2024-03-12 15:27:15 +01:00
Christian Hesse 1934c63512 doc/mod/ssh-keys-import: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 54638924e4 hotspot-to-wpa: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse ec90695e8f packages-update: do not exit with error 2024-03-12 15:27:15 +01:00
Christian Hesse 564a288c4c doc/mod/scriptrunonce: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse b622f47d65 hotspot-to-wpa-cleanup: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse c6639518bc lease-script: do not exit with error 2024-03-12 15:27:15 +01:00
Christian Hesse 4313de6c68 doc/mod/notification-telegram: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 47b67af226 gps-track: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 3acdebad04 hotspot-to-wpa: do not exit with error 2024-03-12 15:27:15 +01:00
Christian Hesse db211a9804 doc/mod/notification-ntfy: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse c1362f54e5 fw-addr-lists: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse ab0b2e27c3 firmware-upgrade-reboot: do not exit with error 2024-03-12 15:27:15 +01:00
Christian Hesse 4a08c09129 doc/mod/notification-matrix: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 894c36fc15 firmware-upgrade-reboot: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 184a769eeb check-routeros-update: do not exit with error 2024-03-12 15:27:15 +01:00
Christian Hesse e2823d8746 doc/mod/notification-email: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse ef5972e9f0 dhcp-to-dns: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 5af8b95444 netwatch-dns: do not exit with error 2024-03-12 15:27:15 +01:00
Christian Hesse 732b86bb86 doc/mod/ipcalc: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 0d1c4cece2 dhcp-lease-comment: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 6712cc101d check-health: do not exit with error 2024-03-12 15:27:15 +01:00
Christian Hesse 73d56b3d5f doc/mod/inspectvar: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse f79206a9b8 daily-psk: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 7fa03ab70e log-forward: do not exit with error 2024-03-12 15:27:15 +01:00
Christian Hesse 9cd84ddffe doc/mod/bridge-port-vlan: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 4ada2e7678 collect-wireless-mac: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 202096c610 doc/mod/bridge-port-to: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 7110b29cba check-routeros-update: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse b6983c8615 doc/log-forward: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse b78556ca41 check-lte-firmware-upgrade: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 91e94c6e38 doc/leds-mode: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 7bf36fa8a5 check-health: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse fd1cb3131d doc/lease-script: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse b1e37c2734 check-certificates: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 8b5c919d8c doc/ipv6-update: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 78f65ead59 certificate-renew-issued: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse c645ab5100 doc/ipsec-to-dns: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 25c9bff6f3 capsman-rolling-upgrade: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse ac51956c3f doc/ip-addr-bridge: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 03309d4fdb capsman-download-packages: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse b45b7606a9 doc/hotspot-to-wpa: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 8d020a4de8 backup-upload: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse e2f6401a15 doc/gps-track: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse b8bd64bac5 backup-partition: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 8ab1df5960 doc/global-wait: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 3eb8fad5ae backup-email: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 900e868caf doc/fw-addr-lists: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 15c68c5660 backup-cloud: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse 2bd2b9b6e3 doc/firmware-upgrade-reboot: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse d0af9d62ea accesslist-duplicates: drop main function, use :do with on-error 2024-03-12 15:27:15 +01:00
Christian Hesse b178e47d6d doc/dhcp-to-dns: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 16b318832a doc/dhcp-lease-comment: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse d1549712ab doc/daily-psk: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 6737c291ca doc/collect-wireless-mac: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse b9b1197c1a doc/check-routeros-update: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse a2afb1d5dc doc/check-lte-firmware-upgrade: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse f68ee9bc00 doc/check-health: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 71ce8709ca doc/check-certificates: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 0c46668e2e doc/certificate-renew-issued: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 50694ec512 doc/capsman-rolling-upgrade: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 9deaed7350 doc/capsman-download-packages: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse a92715ea31 doc/backup-upload: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse acc8cdf8ca doc/backup-partition: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 7b527840b1 doc/backup-email: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 4af1092272 doc/backup-cloud: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse f9fb61ec49 doc/accesslist-duplicates: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 13d0075a48 INITIAL-COMMANDS: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 120d4780fd CONTRIBUTIONS: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse 4f3cf3656c BRANCHES: add badges 2024-03-12 15:27:15 +01:00
Christian Hesse d46156ad92 global-functions: use variable name $ScriptName 2024-03-12 15:27:14 +01:00
Christian Hesse 771ca341b0 Merge branch 'main-function' into next 2024-03-04 21:40:34 +01:00
Christian Hesse 698360f037 update-tunnelbroker: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse ad623f069e update-gre-address: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse 6fd745fc0f telegram-chat: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse 6b1c6a7119 sms-forward: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse 721b6c783b sms-action: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse d6077025b2 ppp-on-up: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse 492edb4263 packages-update: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse 09ea05d989 ospf-to-leds: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse 3c76738915 netwatch-notify: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse 458fd1fdcd netwatch-dns: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse 400516295e mode-button: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse 50e1c45880 log-forward: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse 49650d8b14 lease-script: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse d6ea66ccd3 ipv6-update: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse 85dbe3a868 ipsec-to-dns: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse a36ec397d6 hotspot-to-wpa: move code into function 2024-03-04 21:40:34 +01:00
Christian Hesse 2bf02cf085 hotspot-to-wpa-cleanup: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse a0fc6c30ef gps-track: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse 480ad0c196 fw-addr-lists: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse cf986caf8d firmware-upgrade-reboot: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse 29f544d18d dhcp-to-dns: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse 82ec11f2fc dhcp-lease-comment: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse 31da6b8bd5 daily-psk: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse e2b87c8634 collect-wireless-mac: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse 22eb74cb3a check-routeros-update: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse 450ea2fa48 check-lte-firmware-upgrade: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse 80180b432d check-health: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse fc3fad5e87 check-certificates: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse 2d112c0b33 certificate-renew-issued: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse 4cbf9fab74 capsman-rolling-upgrade: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse c2df671d6f capsman-download-packages: move code into function 2024-03-04 17:04:45 +01:00
Christian Hesse 1c26dde356 backup-upload: move code into function 2024-03-04 16:34:01 +01:00
Christian Hesse 0ded98c9e2 backup-partition: move code into function 2024-03-04 16:33:57 +01:00
Christian Hesse 19fb7b61ea backup-email: move code into function 2024-03-04 16:33:54 +01:00
Christian Hesse 33d129496c backup-cloud: move code into function 2024-03-04 16:33:51 +01:00
Christian Hesse efc2e75f01 accesslist-duplicates: move code into function 2024-03-04 16:33:45 +01:00
Christian Hesse 64aa6ef124 netwatch-notify: check one after another
This can bring an extra delay, but saves a check in most cases.
2024-03-03 20:32:23 +01:00
Christian Hesse 4869d74edf netwatch-notify: handle IPv6 / AAAA resolving 2024-03-02 22:08:40 +01:00
Christian Hesse 50a6914907 netwatch-notify: (mis-)use firewall address-list for lookup...
... and drop the racy code querying dns cache. 😁
2024-03-01 12:30:18 +01:00
Christian Hesse 20d1ad17d7 Merge branch 'fw-addr-lists' into next 2024-02-29 14:22:07 +01:00
Christian Hesse 62790ae091 fw-addr-lists: add support for IPv6 2024-02-29 14:21:58 +01:00
Christian Hesse 0125f102b4 fw-addr-lists: rename variable 2024-02-29 14:21:58 +01:00
Christian Hesse 31966479dc fw-addr-lists: update wording 2024-02-29 14:21:58 +01:00
Christian Hesse 1687e2780f fw-addr-lists: get timeout from loop 2024-02-29 14:21:58 +01:00
Christian Hesse b9e0ffac1d Merge branch 'netwatch-notify' into next 2024-02-29 14:21:46 +01:00
Christian Hesse a924de274c netwatch-notify: handle CNAME to multiple records 2024-02-28 23:01:43 +01:00
Christian Hesse 6f29c640e4 netwatch-notify: move check in DNS cache to local function 2024-02-28 23:01:43 +01:00
Christian Hesse 01d2c3ea7e netwatch-notify: try another workaround
The last one did not make it... Perhaps the cache just needs
a moment to settle?
2024-02-28 23:01:43 +01:00
Christian Hesse 93bed1b081 netwatch-notify: work around race condition
This used to crash every now and then with:

> script;error script error: no such item (4)

I guess this is caused by querying the dns cache just exactly when a
record expires. The chance is maximized: The script is started by
scheduler every minute, and the record's ttl is a multiple of a minute.

Let's query records that are not about to expire immediately, and
try again.
2024-02-28 23:01:43 +01:00
Christian Hesse c2f5272f18 netwatch-notify: restore the check 🥴
This reverts commit 28da1da49e.

Chances are that we have to resolve a CNAME, that does not match when
querying the cache.

How to handle CNAME do multiple A records? 🤨
2024-02-28 23:01:43 +01:00
Christian Hesse 45875ad68e netwatch-notify: simplify the check 2024-02-28 23:01:43 +01:00
Christian Hesse b1199ca50a netwatch-notify: ... and switch state to "unknown" on host update 2024-02-28 23:01:43 +01:00
Christian Hesse 1344694708 netwatch-notify: handle status "down" in its own condition...
... instead of else-branch.

This makes sure to skip hosts that just became "unknown".
(Possible soon!)
2024-02-28 23:01:43 +01:00
Christian Hesse 1c2048628d netwatch-notify: use logical operator, no literal "and"
Just like we do everywhere else.
2024-02-28 23:01:43 +01:00
Christian Hesse 471e0ead05 doc/netwatch-notify: update for multiple records 2024-02-28 23:01:00 +01:00
132 changed files with 4288 additions and 4060 deletions

View file

@ -1,6 +1,13 @@
Installing from branches
========================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](README.md)
> ⚠️ **Warning**: Living on the edge? Great, read on!

View file

@ -1,6 +1,13 @@
Past Contributions
==================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](README.md)
Thanks a lot for your contributions! ❤️

View file

@ -1,6 +1,13 @@
Initial commands
================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](README.md)
> ⚠️ **Warning**: These command are inteneded for initial setup. If you are

View file

@ -5,39 +5,32 @@
CAPSMAN = $(wildcard *.capsman.rsc)
LOCAL = $(wildcard *.local.rsc)
WIFI = $(wildcard *.wifi.rsc)
WIFIWAVE2 = $(wildcard *.wifiwave2.rsc)
MARKDOWN = $(wildcard *.md doc/*.md doc/mod/*.md)
HTML = $(MARKDOWN:.md=.html)
all: $(CAPSMAN) $(LOCAL) $(WIFI) $(WIFIWAVE2) $(HTML)
all: $(CAPSMAN) $(LOCAL) $(WIFI) $(HTML)
%.html: %.md Makefile
markdown $< | sed 's/href="\([-_\./[:alnum:]]*\)\.md"/href="\1.html"/g' > $@
%.capsman.rsc: %.template.rsc Makefile
sed -e '/\/interface\/wifi\//d' -e '/\/interface\/wifiwave2\//d' -e '/\/interface\/wireless\//d' -e 's|%TEMPL%|.capsman|' \
sed -e '/\/interface\/wifi\//d' -e '/\/interface\/wireless\//d' -e 's|%TEMPL%|.capsman|' \
-e '/^# NOT \/caps-man\/ #$$/,/^# NOT \/caps-man\/ #$$/d' \
-e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \
< $< > $@
%.local.rsc: %.template.rsc Makefile
sed -e '/\/caps-man\//d' -e '/\/interface\/wifi\//d' -e '/\/interface\/wifiwave2\//d' -e 's|%TEMPL%|.local|' \
sed -e '/\/caps-man\//d' -e '/\/interface\/wifi\//d' -e 's|%TEMPL%|.local|' \
-e '/^# NOT \/interface\/wireless\/ #$$/,/^# NOT \/interface\/wireless\/ #$$/d' \
-e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \
< $< > $@
%.wifi.rsc: %.template.rsc Makefile
sed -e '/\/caps-man\//d' -e '/\/interface\/wifiwave2\//d' -e '/\/interface\/wireless\//d' -e 's|%TEMPL%|.wifi|' \
sed -e '/\/caps-man\//d' -e '/\/interface\/wireless\//d' -e 's|%TEMPL%|.wifi|' \
-e '/^# NOT \/interface\/wifi\/ #$$/,/^# NOT \/interface\/wifi\/ #$$/d' \
-e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \
< $< > $@
%.wifiwave2.rsc: %.template.rsc Makefile
sed -e '/\/caps-man\//d' -e '/\/interface\/wifi\//d' -e '/\/interface\/wireless\//d' -e 's|%TEMPL%|.wifiwave2|' \
-e '/^# NOT \/interface\/wifiwave2\/ #$$/,/^# NOT \/interface\/wifiwave2\/ #$$/d' \
-e '/^# !!/,/^# !!/c # !! Do not edit this file, it is generated from template!' \
< $< > $@
clean:
rm -f $(HTML)

View file

@ -139,6 +139,11 @@ Save changes and exit with `Ctrl-o`.
![screenshot: edit global-config-overlay](README.d/07-edit-global-config-overlay.avif)
Additionally creating configuration snippets is supported. The script name
of these snippets has to start with `global-config-overlay.d/` to make them
being loaded automatically. This allows to split off parts of the
configuration.
To apply your changes run `global-config`, which will automatically load
the overlay as well:

View file

@ -10,22 +10,25 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:local Seen ({});
:do {
:local ScriptName [ :jobname ];
: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 ];
:if ($Seen->$Mac = 1) do={
/caps-man/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:local Seen ({});
:if ([ :typeof $Remove ] = "num") do={
:put ("Removing numeric id " . $Remove . "...\n");
/caps-man/access-list/remove $Remove;
: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 ];
:if ($Seen->$Mac = 1) do={
/caps-man/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:if ([ :typeof $Remove ] = "num") do={
:put ("Removing numeric id " . $Remove . "...\n");
/caps-man/access-list/remove $Remove;
}
}
:set ($Seen->$Mac) 1;
}
:set ($Seen->$Mac) 1;
}
} on-error={ }

View file

@ -10,22 +10,25 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:local Seen ({});
:do {
:local ScriptName [ :jobname ];
: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 ];
:if ($Seen->$Mac = 1) do={
/interface/wireless/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:local Seen ({});
:if ([ :typeof $Remove ] = "num") do={
:put ("Removing numeric id " . $Remove . "...\n");
/interface/wireless/access-list/remove $Remove;
: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 ];
:if ($Seen->$Mac = 1) do={
/interface/wireless/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:if ([ :typeof $Remove ] = "num") do={
:put ("Removing numeric id " . $Remove . "...\n");
/interface/wireless/access-list/remove $Remove;
}
}
:set ($Seen->$Mac) 1;
}
:set ($Seen->$Mac) 1;
}
} on-error={ }

View file

@ -11,34 +11,33 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:local Seen ({});
:do {
:local ScriptName [ :jobname ];
:foreach AccList in=[ /caps-man/access-list/find where mac-address!="00:00:00:00:00:00" ] do={
:foreach AccList in=[ /interface/wifi/access-list/find where mac-address!="00:00:00:00:00:00" ] do={
:foreach AccList in=[ /interface/wifiwave2/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 [ /caps-man/access-list/get $AccList mac-address ];
:local Mac [ /interface/wifi/access-list/get $AccList mac-address ];
:local Mac [ /interface/wifiwave2/access-list/get $AccList mac-address ];
:local Mac [ /interface/wireless/access-list/get $AccList mac-address ];
:if ($Seen->$Mac = 1) do={
/caps-man/access-list/print where mac-address=$Mac;
/interface/wifi/access-list/print where mac-address=$Mac;
/interface/wifiwave2/access-list/print where mac-address=$Mac;
/interface/wireless/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:local Seen ({});
:if ([ :typeof $Remove ] = "num") do={
:put ("Removing numeric id " . $Remove . "...\n");
/caps-man/access-list/remove $Remove;
/interface/wifi/access-list/remove $Remove;
/interface/wifiwave2/access-list/remove $Remove;
/interface/wireless/access-list/remove $Remove;
:foreach AccList in=[ /caps-man/access-list/find where mac-address!="00:00:00:00:00:00" ] do={
:foreach AccList in=[ /interface/wifi/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 [ /caps-man/access-list/get $AccList mac-address ];
:local Mac [ /interface/wifi/access-list/get $AccList mac-address ];
:local Mac [ /interface/wireless/access-list/get $AccList mac-address ];
:if ($Seen->$Mac = 1) do={
/caps-man/access-list/print where mac-address=$Mac;
/interface/wifi/access-list/print where mac-address=$Mac;
/interface/wireless/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:if ([ :typeof $Remove ] = "num") do={
:put ("Removing numeric id " . $Remove . "...\n");
/caps-man/access-list/remove $Remove;
/interface/wifi/access-list/remove $Remove;
/interface/wireless/access-list/remove $Remove;
}
}
:set ($Seen->$Mac) 1;
}
:set ($Seen->$Mac) 1;
}
} on-error={ }

View file

@ -10,22 +10,25 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:local Seen ({});
:do {
:local ScriptName [ :jobname ];
:foreach AccList in=[ /interface/wifi/access-list/find where mac-address!="00:00:00:00:00:00" ] do={
:local Mac [ /interface/wifi/access-list/get $AccList mac-address ];
:if ($Seen->$Mac = 1) do={
/interface/wifi/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:local Seen ({});
:if ([ :typeof $Remove ] = "num") do={
:put ("Removing numeric id " . $Remove . "...\n");
/interface/wifi/access-list/remove $Remove;
:foreach AccList in=[ /interface/wifi/access-list/find where mac-address!="00:00:00:00:00:00" ] do={
:local Mac [ /interface/wifi/access-list/get $AccList mac-address ];
:if ($Seen->$Mac = 1) do={
/interface/wifi/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:if ([ :typeof $Remove ] = "num") do={
:put ("Removing numeric id " . $Remove . "...\n");
/interface/wifi/access-list/remove $Remove;
}
}
:set ($Seen->$Mac) 1;
}
:set ($Seen->$Mac) 1;
}
} on-error={ }

View file

@ -1,31 +0,0 @@
#!rsc by RouterOS
# RouterOS script: accesslist-duplicates.wifiwave2
# Copyright (c) 2018-2024 Christian Hesse <mail@eworm.de>
# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md
#
# requires RouterOS, version=7.12
#
# print duplicate antries in wireless access list
# https://git.eworm.de/cgit/routeros-scripts/about/doc/accesslist-duplicates.md
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:local Seen ({});
:foreach AccList in=[ /interface/wifiwave2/access-list/find where mac-address!="00:00:00:00:00:00" ] do={
:local Mac [ /interface/wifiwave2/access-list/get $AccList mac-address ];
:if ($Seen->$Mac = 1) do={
/interface/wifiwave2/access-list/print where mac-address=$Mac;
:local Remove [ :tonum [ /terminal/ask prompt="\nNumeric id to remove, any key to skip!" ] ];
:if ([ :typeof $Remove ] = "num") do={
:put ("Removing numeric id " . $Remove . "...\n");
/interface/wifiwave2/access-list/remove $Remove;
}
}
:set ($Seen->$Mac) 1;
}

View file

@ -9,55 +9,77 @@
# upload backup to MikroTik cloud
# https://git.eworm.de/cgit/routeros-scripts/about/doc/backup-cloud.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global BackupPassword;
:global BackupRandomDelay;
:global Identity;
:global DeviceInfo;
:global FormatLine;
:global HumanReadableNum;
:global LogPrintExit2;
:global RandomDelay;
:global ScriptFromTerminal;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global WaitFullyConnected;
$ScriptLock $0;
$WaitFullyConnected;
:if ([ $ScriptFromTerminal $0 ] = false && $BackupRandomDelay > 0) do={
$RandomDelay $BackupRandomDelay;
}
:do {
# we are not interested in output, but print is
# required to fetch information from cloud
/system/backup/cloud/print as-value;
:if ([ :len [ /system/backup/cloud/find ] ] > 0) do={
/system/backup/cloud/upload-file action=create-and-upload \
password=$BackupPassword replace=[ get ([ find ]->0) name ];
} else={
/system/backup/cloud/upload-file action=create-and-upload \
password=$BackupPassword;
}
:local Cloud [ /system/backup/cloud/get ([ find ]->0) ];
:local ScriptName [ :jobname ];
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "floppy-disk,cloud" ] . "Cloud backup"); \
message=("Uploaded backup for " . $Identity . " to cloud.\n\n" . \
[ $DeviceInfo ] . "\n\n" . \
[ $FormatLine "Name" ($Cloud->"name") ] . "\n" . \
[ $FormatLine "Size" ([ $HumanReadableNum ($Cloud->"size") 1024 ] . "iB") ] . "\n" . \
[ $FormatLine "Download key" ($Cloud->"secret-download-key") ]); silent=true });
} on-error={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "floppy-disk,warning-sign" ] . "Cloud backup failed"); \
message=("Failed uploading backup for " . $Identity . " to cloud!\n\n" . [ $DeviceInfo ]) });
$LogPrintExit2 error $0 ("Failed uploading backup for " . $Identity . " to cloud!") true;
}
:global BackupRandomDelay;
:global Identity;
:global PackagesUpdateBackupFailure;
:global DeviceInfo;
:global FormatLine;
:global HumanReadableNum;
:global LogPrint;
:global MkDir;
:global RandomDelay;
:global ScriptFromTerminal;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global WaitForFile;
:global WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set PackagesUpdateBackupFailure true;
:error false;
}
$WaitFullyConnected;
:if ([ $ScriptFromTerminal $ScriptName ] = false && $BackupRandomDelay > 0) do={
$RandomDelay $BackupRandomDelay;
}
:if ([ $MkDir ("tmpfs/backup-cloud") ] = false) do={
$LogPrint error $ScriptName ("Failed creating directory!");
:error false;
}
:execute {
:global BackupPassword;
# we are not interested in output, but print is
# required to fetch information from cloud
/system/backup/cloud/print as-value;
:delay 20ms;
:if ([ :len [ /system/backup/cloud/find ] ] > 0) do={
/system/backup/cloud/upload-file action=create-and-upload \
password=$BackupPassword replace=[ get ([ find ]->0) name ];
} else={
/system/backup/cloud/upload-file action=create-and-upload \
password=$BackupPassword;
}
/file/add name="tmpfs/backup-cloud/done";
} as-string;
:if ([ $WaitForFile "tmpfs/backup-cloud/done" ] = true) do={
:local Cloud [ /system/backup/cloud/get ([ find ]->0) ];
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "floppy-disk,cloud" ] . "Cloud backup"); \
message=("Uploaded backup for " . $Identity . " to cloud.\n\n" . \
[ $DeviceInfo ] . "\n\n" . \
[ $FormatLine "Name" ($Cloud->"name") ] . "\n" . \
[ $FormatLine "Size" ([ $HumanReadableNum ($Cloud->"size") 1024 ] . "iB") ] . "\n" . \
[ $FormatLine "Download key" ($Cloud->"secret-download-key") ]); silent=true });
} else={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "floppy-disk,warning-sign" ] . "Cloud backup failed"); \
message=("Failed uploading backup for " . $Identity . " to cloud!\n\n" . [ $DeviceInfo ]) });
$LogPrint error $ScriptName ("Failed uploading backup for " . $Identity . " to cloud!");
:set PackagesUpdateBackupFailure true;
:error false;
}
/file/remove "tmpfs/backup-cloud";
} on-error={ }

View file

@ -9,104 +9,116 @@
# create and email backup and config file
# https://git.eworm.de/cgit/routeros-scripts/about/doc/backup-email.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global BackupPassword;
:global BackupRandomDelay;
:global BackupSendBinary;
:global BackupSendExport;
:global BackupSendGlobalConfig;
:global Domain;
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global CleanName;
:global DeviceInfo;
:global FormatLine;
:global LogPrintExit2;
:global MkDir;
:global RandomDelay;
:global ScriptFromTerminal;
:global ScriptLock;
:global SendEMail2;
:global SymbolForNotification;
:global WaitForFile;
:global WaitFullyConnected;
:global BackupPassword;
:global BackupRandomDelay;
:global BackupSendBinary;
:global BackupSendExport;
:global BackupSendGlobalConfig;
:global Domain;
:global Identity;
:global PackagesUpdateBackupFailure;
:if ([ :typeof $SendEMail2 ] = "nothing") do={
$LogPrintExit2 error $0 ("The module for sending notifications via e-mail is not installed.") true;
}
:global CleanName;
:global DeviceInfo;
:global FormatLine;
:global LogPrint;
:global MkDir;
:global RandomDelay;
:global ScriptFromTerminal;
:global ScriptLock;
:global SendEMail2;
:global SymbolForNotification;
:global WaitForFile;
:global WaitFullyConnected;
:if ($BackupSendBinary != true && \
$BackupSendExport != true) do={
$LogPrintExit2 error $0 ("Configured to send neither backup nor config export.") true;
}
$ScriptLock $0;
$WaitFullyConnected;
:if ([ $ScriptFromTerminal $0 ] = false && $BackupRandomDelay > 0) do={
$RandomDelay $BackupRandomDelay;
}
# filename based on identity
:local DirName ("tmpfs/" . $0);
:local FileName [ $CleanName ($Identity . "." . $Domain) ];
:local FilePath ($DirName . "/" . $FileName);
:local BackupFile "none";
:local ExportFile "none";
:local ConfigFile "none";
:local Attach ({});
:if ([ $MkDir $DirName ] = false) do={
$LogPrintExit2 error $0 ("Failed creating directory!") true;
}
# binary backup
:if ($BackupSendBinary = true) do={
/system/backup/save encryption=aes-sha256 name=$FilePath password=$BackupPassword;
$WaitForFile ($FilePath . ".backup");
:set BackupFile ($FileName . ".backup");
:set Attach ($Attach, ($FilePath . ".backup"));
}
# create configuration export
:if ($BackupSendExport = true) do={
/export terse show-sensitive file=$FilePath;
$WaitForFile ($FilePath . ".rsc");
:set ExportFile ($FileName . ".rsc");
:set Attach ($Attach, ($FilePath . ".rsc"));
}
# global-config-overlay
:if ($BackupSendGlobalConfig = true) do={
# Do *NOT* use '/file/add ...' here, as it is limited to 4095 bytes!
:execute script={ :put [ /system/script/get global-config-overlay source ]; } \
file=($FilePath . ".conf\00");
$WaitForFile ($FilePath . ".conf");
:set ConfigFile ($FileName . ".conf");
:set Attach ($Attach, ($FilePath . ".conf"));
}
# send email with status and files
$SendEMail2 ({ origin=$0; \
subject=([ $SymbolForNotification "floppy-disk,incoming-envelope" ] . \
"Backup & Config"); \
message=("See attached files for backup and config export for " . \
$Identity . ".\n\n" . \
[ $DeviceInfo ] . "\n\n" . \
[ $FormatLine "Backup file" $BackupFile ] . "\n" . \
[ $FormatLine "Export file" $ExportFile ] . "\n" . \
[ $FormatLine "Config file" $ConfigFile ]); \
attach=$Attach; remove-attach=true });
# wait for the mail to be sent
:local I 0;
:while ([ :len [ /file/find where name ~ ($FilePath . "\\.(backup|rsc)\$") ] ] > 0) do={
:if ($I >= 120) do={
$LogPrintExit2 warning $0 ("Files are still available, sending e-mail failed.") true;
:if ([ :typeof $SendEMail2 ] = "nothing") do={
$LogPrint error $ScriptName ("The module for sending notifications via e-mail is not installed.");
:error false;
}
:delay 1s;
:set I ($I + 1);
}
:if ($BackupSendBinary != true && \
$BackupSendExport != true) do={
$LogPrint error $ScriptName ("Configured to send neither backup nor config export.");
:error false;
}
:if ([ $ScriptLock $ScriptName ] = false) do={
:set PackagesUpdateBackupFailure true;
:error false;
}
$WaitFullyConnected;
:if ([ $ScriptFromTerminal $ScriptName ] = false && $BackupRandomDelay > 0) do={
$RandomDelay $BackupRandomDelay;
}
# filename based on identity
:local DirName ("tmpfs/" . $ScriptName);
:local FileName [ $CleanName ($Identity . "." . $Domain) ];
:local FilePath ($DirName . "/" . $FileName);
:local BackupFile "none";
:local ExportFile "none";
:local ConfigFile "none";
:local Attach ({});
:if ([ $MkDir $DirName ] = false) do={
$LogPrint error $ScriptName ("Failed creating directory!");
:error false;
}
# binary backup
:if ($BackupSendBinary = true) do={
/system/backup/save encryption=aes-sha256 name=$FilePath password=$BackupPassword;
$WaitForFile ($FilePath . ".backup");
:set BackupFile ($FileName . ".backup");
:set Attach ($Attach, ($FilePath . ".backup"));
}
# create configuration export
:if ($BackupSendExport = true) do={
/export terse show-sensitive file=$FilePath;
$WaitForFile ($FilePath . ".rsc");
:set ExportFile ($FileName . ".rsc");
:set Attach ($Attach, ($FilePath . ".rsc"));
}
# global-config-overlay
:if ($BackupSendGlobalConfig = true) do={
# Do *NOT* use '/file/add ...' here, as it is limited to 4095 bytes!
:execute script={ :put [ /system/script/get global-config-overlay source ]; } \
file=($FilePath . ".conf\00");
$WaitForFile ($FilePath . ".conf");
:set ConfigFile ($FileName . ".conf");
:set Attach ($Attach, ($FilePath . ".conf"));
}
# send email with status and files
$SendEMail2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "floppy-disk,incoming-envelope" ] . \
"Backup & Config"); \
message=("See attached files for backup and config export for " . \
$Identity . ".\n\n" . \
[ $DeviceInfo ] . "\n\n" . \
[ $FormatLine "Backup file" $BackupFile ] . "\n" . \
[ $FormatLine "Export file" $ExportFile ] . "\n" . \
[ $FormatLine "Config file" $ConfigFile ]); \
attach=$Attach; remove-attach=true });
# wait for the mail to be sent
:local I 0;
:while ([ :len [ /file/find where name ~ ($FilePath . "\\.(backup|rsc)\$") ] ] > 0) do={
:if ($I >= 120) do={
$LogPrint warning $ScriptName ("Files are still available, sending e-mail failed.");
:set PackagesUpdateBackupFailure true;
:error false;
}
:delay 1s;
:set I ($I + 1);
}
} on-error={ }

View file

@ -9,37 +9,49 @@
# save configuration to fallback partition
# https://git.eworm.de/cgit/routeros-scripts/about/doc/backup-partition.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global LogPrintExit2;
:global ScriptLock;
$ScriptLock $0;
:if ([ :len [ /partitions/find ] ] < 2) do={
$LogPrintExit2 error $0 ("Device does not have a fallback partition.") true;
}
:local ActiveRunning [ /partitions/find where active running ];
:if ([ :len $ActiveRunning ] < 1) do={
$LogPrintExit2 error $0 ("Device is not running from active partition.") true;
}
:local FallbackTo [ /partitions/get $ActiveRunning fallback-to ];
:do {
/system/scheduler/add start-time=startup name="running-from-backup-partition" \
on-event=(":log warning (\"Running from partition '\" . " . \
"[ /partitions/get [ find where running ] name ] . \"'!\")");
/partitions/save-config-to $FallbackTo;
/system/scheduler/remove "running-from-backup-partition";
$LogPrintExit2 info $0 ("Saved configuration to partition '" . \
$FallbackTo . "'.") false;
} on-error={
/system/scheduler/remove [ find where name="running-from-backup-partition" ];
$LogPrintExit2 error $0 ("Failed saving configuration to partition '" . \
$FallbackTo . "'!") true;
}
:local ScriptName [ :jobname ];
:global PackagesUpdateBackupFailure;
:global LogPrint;
:global ScriptLock;
:if ([ $ScriptLock $ScriptName ] = false) do={
:set PackagesUpdateBackupFailure true;
:error false;
}
:if ([ :len [ /partitions/find ] ] < 2) do={
$LogPrint error $ScriptName ("Device does not have a fallback partition.");
:set PackagesUpdateBackupFailure true;
:error false;
}
:local ActiveRunning [ /partitions/find where active running ];
:if ([ :len $ActiveRunning ] < 1) do={
$LogPrint error $ScriptName ("Device is not running from active partition.");
:set PackagesUpdateBackupFailure true;
:error false;
}
:local FallbackTo [ /partitions/get $ActiveRunning fallback-to ];
:do {
/system/scheduler/add start-time=startup name="running-from-backup-partition" \
on-event=(":log warning (\"Running from partition '\" . " . \
"[ /partitions/get [ find where running ] name ] . \"'!\")");
/partitions/save-config-to $FallbackTo;
/system/scheduler/remove "running-from-backup-partition";
$LogPrint info $ScriptName ("Saved configuration to partition '" . $FallbackTo . "'.");
} on-error={
/system/scheduler/remove [ find where name="running-from-backup-partition" ];
$LogPrint error $ScriptName ("Failed saving configuration to partition '" . $FallbackTo . "'!");
:set PackagesUpdateBackupFailure true;
:error false;
}
} on-error={ }

View file

@ -9,143 +9,153 @@
# create and upload backup and config file
# https://git.eworm.de/cgit/routeros-scripts/about/doc/backup-upload.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global BackupPassword;
:global BackupRandomDelay;
:global BackupSendBinary;
:global BackupSendExport;
:global BackupSendGlobalConfig;
:global BackupUploadPass;
:global BackupUploadUrl;
:global BackupUploadUser;
:global Domain;
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global CleanName;
:global DeviceInfo;
:global IfThenElse;
:global LogPrintExit2;
:global MkDir;
:global RandomDelay;
:global ScriptFromTerminal;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global WaitForFile;
:global WaitFullyConnected;
:global BackupPassword;
:global BackupRandomDelay;
:global BackupSendBinary;
:global BackupSendExport;
:global BackupSendGlobalConfig;
:global BackupUploadPass;
:global BackupUploadUrl;
:global BackupUploadUser;
:global Domain;
:global Identity;
:global PackagesUpdateBackupFailure;
:if ($BackupSendBinary != true && \
$BackupSendExport != true) do={
$LogPrintExit2 error $0 ("Configured to send neither backup nor config export.") true;
}
$ScriptLock $0;
$WaitFullyConnected;
:if ([ $ScriptFromTerminal $0 ] = false && $BackupRandomDelay > 0) do={
$RandomDelay $BackupRandomDelay;
}
# filename based on identity
:local DirName ("tmpfs/" . $0);
:local FileName [ $CleanName ($Identity . "." . $Domain) ];
:local FilePath ($DirName . "/" . $FileName);
:local BackupFile "none";
:local ExportFile "none";
:local ConfigFile "none";
:local Failed 0;
:if ([ $MkDir $DirName ] = false) do={
$LogPrintExit2 error $0 ("Failed creating directory!") true;
}
# binary backup
:if ($BackupSendBinary = true) do={
/system/backup/save encryption=aes-sha256 name=$FilePath password=$BackupPassword;
$WaitForFile ($FilePath . ".backup");
:do {
/tool/fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".backup") \
user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".backup");
:set BackupFile [ /file/get ($FilePath . ".backup") ];
:set ($BackupFile->"name") ($FileName . ".backup");
} on-error={
$LogPrintExit2 error $0 ("Uploading backup file failed!") false;
:set BackupFile "failed";
:set Failed 1;
}
/file/remove ($FilePath . ".backup");
}
# create configuration export
:if ($BackupSendExport = true) do={
/export terse show-sensitive file=$FilePath;
$WaitForFile ($FilePath . ".rsc");
:do {
/tool/fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".rsc") \
user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".rsc");
:set ExportFile [ /file/get ($FilePath . ".rsc") ];
:set ($ExportFile->"name") ($FileName . ".rsc");
} on-error={
$LogPrintExit2 error $0 ("Uploading configuration export failed!") false;
:set ExportFile "failed";
:set Failed 1;
}
/file/remove ($FilePath . ".rsc");
}
# global-config-overlay
:if ($BackupSendGlobalConfig = true) do={
# Do *NOT* use '/file/add ...' here, as it is limited to 4095 bytes!
:execute script={ :put [ /system/script/get global-config-overlay source ]; } \
file=($FilePath . ".conf\00");
$WaitForFile ($FilePath . ".conf");
:do {
/tool/fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".conf") \
user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".conf");
:set ConfigFile [ /file/get ($FilePath . ".conf") ];
:set ($ConfigFile->"name") ($FileName . ".conf");
} on-error={
$LogPrintExit2 error $0 ("Uploading global-config-overlay failed!") false;
:set ConfigFile "failed";
:set Failed 1;
}
/file/remove ($FilePath . ".conf");
}
:local FileInfo do={
:local Name $1;
:local File $2;
:global FormatLine;
:global HumanReadableNum;
:global CleanName;
:global DeviceInfo;
:global IfThenElse;
:global LogPrint;
:global MkDir;
:global RandomDelay;
:global ScriptFromTerminal;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global WaitForFile;
:global WaitFullyConnected;
:return \
[ $IfThenElse ([ :typeof $File ] = "array") \
($Name . ":\n" . [ $FormatLine " name" ($File->"name") ] . "\n" . \
[ $FormatLine " size" ([ $HumanReadableNum ($File->"size") 1024 ] . "iB") ]) \
[ $FormatLine $Name $File ] ];
}
:if ($BackupSendBinary != true && \
$BackupSendExport != true) do={
$LogPrint error $ScriptName ("Configured to send neither backup nor config export.");
:error false;
}
$SendNotification2 ({ origin=$0; \
subject=[ $IfThenElse ($Failed > 0) \
([ $SymbolForNotification "floppy-disk,warning-sign" ] . "Backup & Config upload with failure") \
([ $SymbolForNotification "floppy-disk,arrow-up" ] . "Backup & Config upload") ]; \
message=("Backup and config export upload for " . $Identity . ".\n\n" . \
[ $DeviceInfo ] . "\n\n" . \
[ $FileInfo "Backup file" $BackupFile ] . "\n" . \
[ $FileInfo "Export file" $ExportFile ] . "\n" . \
[ $FileInfo "Config file" $ConfigFile ]); silent=true });
:if ([ $ScriptLock $ScriptName ] = false) do={
:set PackagesUpdateBackupFailure true;
:error false;
}
$WaitFullyConnected;
:if ($Failed = 1) do={
:error "An error occured!";
}
:if ([ $ScriptFromTerminal $ScriptName ] = false && $BackupRandomDelay > 0) do={
$RandomDelay $BackupRandomDelay;
}
# filename based on identity
:local DirName ("tmpfs/" . $ScriptName);
:local FileName [ $CleanName ($Identity . "." . $Domain) ];
:local FilePath ($DirName . "/" . $FileName);
:local BackupFile "none";
:local ExportFile "none";
:local ConfigFile "none";
:local Failed 0;
:if ([ $MkDir $DirName ] = false) do={
$LogPrint error $ScriptName ("Failed creating directory!");
:error false;
}
# binary backup
:if ($BackupSendBinary = true) do={
/system/backup/save encryption=aes-sha256 name=$FilePath password=$BackupPassword;
$WaitForFile ($FilePath . ".backup");
:do {
/tool/fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".backup") \
user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".backup");
:set BackupFile [ /file/get ($FilePath . ".backup") ];
:set ($BackupFile->"name") ($FileName . ".backup");
} on-error={
$LogPrint error $ScriptName ("Uploading backup file failed!");
:set BackupFile "failed";
:set Failed 1;
}
/file/remove ($FilePath . ".backup");
}
# create configuration export
:if ($BackupSendExport = true) do={
/export terse show-sensitive file=$FilePath;
$WaitForFile ($FilePath . ".rsc");
:do {
/tool/fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".rsc") \
user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".rsc");
:set ExportFile [ /file/get ($FilePath . ".rsc") ];
:set ($ExportFile->"name") ($FileName . ".rsc");
} on-error={
$LogPrint error $ScriptName ("Uploading configuration export failed!");
:set ExportFile "failed";
:set Failed 1;
}
/file/remove ($FilePath . ".rsc");
}
# global-config-overlay
:if ($BackupSendGlobalConfig = true) do={
# Do *NOT* use '/file/add ...' here, as it is limited to 4095 bytes!
:execute script={ :put [ /system/script/get global-config-overlay source ]; } \
file=($FilePath . ".conf\00");
$WaitForFile ($FilePath . ".conf");
:do {
/tool/fetch upload=yes url=($BackupUploadUrl . "/" . $FileName . ".conf") \
user=$BackupUploadUser password=$BackupUploadPass src-path=($FilePath . ".conf");
:set ConfigFile [ /file/get ($FilePath . ".conf") ];
:set ($ConfigFile->"name") ($FileName . ".conf");
} on-error={
$LogPrint error $ScriptName ("Uploading global-config-overlay failed!");
:set ConfigFile "failed";
:set Failed 1;
}
/file/remove ($FilePath . ".conf");
}
:local FileInfo do={
:local Name $1;
:local File $2;
:global FormatLine;
:global HumanReadableNum;
:global IfThenElse;
:return \
[ $IfThenElse ([ :typeof $File ] = "array") \
($Name . ":\n" . [ $FormatLine " name" ($File->"name") ] . "\n" . \
[ $FormatLine " size" ([ $HumanReadableNum ($File->"size") 1024 ] . "iB") ]) \
[ $FormatLine $Name $File ] ];
}
$SendNotification2 ({ origin=$ScriptName; \
subject=[ $IfThenElse ($Failed > 0) \
([ $SymbolForNotification "floppy-disk,warning-sign" ] . "Backup & Config upload with failure") \
([ $SymbolForNotification "floppy-disk,arrow-up" ] . "Backup & Config upload") ]; \
message=("Backup and config export upload for " . $Identity . ".\n\n" . \
[ $DeviceInfo ] . "\n\n" . \
[ $FileInfo "Backup file" $BackupFile ] . "\n" . \
[ $FileInfo "Export file" $ExportFile ] . "\n" . \
[ $FileInfo "Config file" $ConfigFile ]); silent=true });
:if ($Failed = 1) do={
:set PackagesUpdateBackupFailure true;
:error false;
}
} on-error={ }

View file

@ -11,66 +11,73 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global CleanFilePath;
:global DownloadPackage;
:global LogPrintExit2;
:global MkDir;
:global ScriptLock;
:global WaitFullyConnected;
:do {
:local ScriptName [ :jobname ];
$ScriptLock $0;
$WaitFullyConnected;
:global CleanFilePath;
:global DownloadPackage;
:global LogPrint;
:global MkDir;
:global ScriptLock;
:global WaitFullyConnected;
:local PackagePath [ $CleanFilePath [ /caps-man/manager/get package-path ] ];
:local InstalledVersion [ /system/package/update/get installed-version ];
:local Updated false;
:if ([ :len $PackagePath ] = 0) do={
$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 ([ $MkDir $PackagePath ] = false) do={
$LogPrintExit2 warning $0 ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!") true;
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
$LogPrintExit2 info $0 ("Created directory at CAPsMAN package path (" . $PackagePath . \
"). Please place your packages!") false;
}
$WaitFullyConnected;
:foreach Package in=[ /file/find where type=package \
package-version!=$InstalledVersion name~("^" . $PackagePath) ] do={
:local File [ /file/get $Package ];
:if ($File->"package-architecture" = "mips") do={
:set ($File->"package-architecture") "mipsbe";
}
:if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \
($File->"package-architecture") $PackagePath ] = true) do={
:set Updated true;
/file/remove $Package;
}
}
:local PackagePath [ $CleanFilePath [ /caps-man/manager/get package-path ] ];
:local InstalledVersion [ /system/package/update/get installed-version ];
:local Updated false;
:if ([ :len [ /file/find where type=package name~("^" . $PackagePath) ] ] = 0) do={
$LogPrintExit2 info $0 ("No packages available, downloading default set.") false;
:foreach Arch in={ "arm"; "mipsbe" } do={
:foreach Package in={ "routeros"; "wireless" } do={
:if ([ $DownloadPackage $Package $InstalledVersion $Arch $PackagePath ] = true) do={
:set Updated true;
:if ([ :len $PackagePath ] = 0) do={
$LogPrint warning $ScriptName ("The CAPsMAN package path is not defined, can not download packages.");
:error false;
}
:if ([ :len [ /file/find where name=$PackagePath type="directory" ] ] = 0) do={
:if ([ $MkDir $PackagePath ] = false) do={
$LogPrint warning $ScriptName ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!");
:error false;
}
$LogPrint info $ScriptName ("Created directory at CAPsMAN package path (" . $PackagePath . \
"). Please place your packages!");
}
:foreach Package in=[ /file/find where type=package \
package-version!=$InstalledVersion name~("^" . $PackagePath) ] do={
:local File [ /file/get $Package ];
:if ($File->"package-architecture" = "mips") do={
:set ($File->"package-architecture") "mipsbe";
}
:if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \
($File->"package-architecture") $PackagePath ] = true) do={
:set Updated true;
/file/remove $Package;
}
}
:if ([ :len [ /file/find where type=package name~("^" . $PackagePath) ] ] = 0) do={
$LogPrint info $ScriptName ("No packages available, downloading default set.");
:foreach Arch in={ "arm"; "mipsbe" } do={
:foreach Package in={ "routeros"; "wireless" } do={
:if ([ $DownloadPackage $Package $InstalledVersion $Arch $PackagePath ] = true) do={
:set Updated true;
}
}
}
}
}
:if ($Updated = true) do={
:local Script ([ /system/script/find where source~"\n# provides: capsman-rolling-upgrade\n" ]->0);
:if ([ :len $Script ] > 0) do={
/system/script/run $Script;
} else={
/caps-man/remote-cap/upgrade [ find where version!=$InstalledVersion ];
:if ($Updated = true) do={
:local Script ([ /system/script/find where source~"\n# provides: capsman-rolling-upgrade\n" ]->0);
:if ([ :len $Script ] > 0) do={
/system/script/run $Script;
} else={
/caps-man/remote-cap/upgrade [ find where version!=$InstalledVersion ];
}
}
}
} on-error={ }

View file

@ -12,85 +12,83 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global CleanFilePath;
:global DownloadPackage;
:global LogPrintExit2;
:global MkDir;
:global ScriptLock;
:global WaitFullyConnected;
:do {
:local ScriptName [ :jobname ];
$ScriptLock $0;
$WaitFullyConnected;
:global CleanFilePath;
:global DownloadPackage;
:global LogPrint;
:global MkDir;
:global ScriptLock;
:global WaitFullyConnected;
:local PackagePath [ $CleanFilePath [ /caps-man/manager/get package-path ] ];
:local PackagePath [ $CleanFilePath [ /interface/wifi/capsman/get package-path ] ];
:local PackagePath [ $CleanFilePath [ /interface/wifiwave2/capsman/get package-path ] ];
:local InstalledVersion [ /system/package/update/get installed-version ];
:local Updated false;
:if ([ :len $PackagePath ] = 0) do={
$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 ([ $MkDir $PackagePath ] = false) do={
$LogPrintExit2 warning $0 ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!") true;
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
$LogPrintExit2 info $0 ("Created directory at CAPsMAN package path (" . $PackagePath . \
"). Please place your packages!") false;
}
$WaitFullyConnected;
:foreach Package in=[ /file/find where type=package \
package-version!=$InstalledVersion name~("^" . $PackagePath) ] do={
:local File [ /file/get $Package ];
:if ($File->"package-architecture" = "mips") do={
:set ($File->"package-architecture") "mipsbe";
}
:if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \
($File->"package-architecture") $PackagePath ] = true) do={
:set Updated true;
/file/remove $Package;
}
}
:local PackagePath [ $CleanFilePath [ /caps-man/manager/get package-path ] ];
:local PackagePath [ $CleanFilePath [ /interface/wifi/capsman/get package-path ] ];
:local InstalledVersion [ /system/package/update/get installed-version ];
:local Updated false;
:if ([ :len [ /file/find where type=package name~("^" . $PackagePath) ] ] = 0) do={
$LogPrintExit2 info $0 ("No packages available, downloading default set.") false;
:if ([ :len $PackagePath ] = 0) do={
$LogPrint warning $ScriptName ("The CAPsMAN package path is not defined, can not download packages.");
:error false;
}
:if ([ :len [ /file/find where name=$PackagePath type="directory" ] ] = 0) do={
:if ([ $MkDir $PackagePath ] = false) do={
$LogPrint warning $ScriptName ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!");
:error false;
}
$LogPrint info $ScriptName ("Created directory at CAPsMAN package path (" . $PackagePath . \
"). Please place your packages!");
}
:foreach Package in=[ /file/find where type=package \
package-version!=$InstalledVersion name~("^" . $PackagePath) ] do={
:local File [ /file/get $Package ];
:if ($File->"package-architecture" = "mips") do={
:set ($File->"package-architecture") "mipsbe";
}
:if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \
($File->"package-architecture") $PackagePath ] = true) do={
:set Updated true;
/file/remove $Package;
}
}
:if ([ :len [ /file/find where type=package name~("^" . $PackagePath) ] ] = 0) do={
$LogPrint info $ScriptName ("No packages available, downloading default set.");
# NOT /interface/wifi/ #
# NOT /interface/wifiwave2/ #
:foreach Arch in={ "arm"; "mipsbe" } do={
:foreach Package in={ "routeros"; "wireless" } do={
:foreach Arch in={ "arm"; "mipsbe" } do={
:foreach Package in={ "routeros"; "wireless" } do={
# NOT /interface/wifi/ #
# NOT /interface/wifiwave2/ #
# NOT /caps-man/ #
:foreach Arch in={ "arm"; "arm64" } do={
# NOT /interface/wifi/ #
:foreach Package in={ "routeros"; "wifiwave2" } do={
# NOT /interface/wifi/ #
# NOT /interface/wifiwave2/ #
:local Packages { "arm"={ "routeros"; "wifi-qcom"; "wifi-qcom-ac" };
"arm64"={ "routeros"; "wifi-qcom" } };
:foreach Package in=($Packages->$Arch) do={
# NOT /interface/wifiwave2/ #
:foreach Arch in={ "arm"; "arm64" } do={
:local Packages { "arm"={ "routeros"; "wifi-qcom"; "wifi-qcom-ac" };
"arm64"={ "routeros"; "wifi-qcom" } };
:foreach Package in=($Packages->$Arch) do={
# NOT /caps-man/ #
:if ([ $DownloadPackage $Package $InstalledVersion $Arch $PackagePath ] = true) do={
:set Updated true;
:if ([ $DownloadPackage $Package $InstalledVersion $Arch $PackagePath ] = true) do={
:set Updated true;
}
}
}
}
}
:if ($Updated = true) do={
:local Script ([ /system/script/find where source~"\n# provides: capsman-rolling-upgrade\n" ]->0);
:if ([ :len $Script ] > 0) do={
/system/script/run $Script;
} else={
/caps-man/remote-cap/upgrade [ find where version!=$InstalledVersion ];
/interface/wifi/capsman/remote-cap/upgrade [ find where version!=$InstalledVersion ];
/interface/wifiwave2/capsman/remote-cap/upgrade [ find where version!=$InstalledVersion ];
:if ($Updated = true) do={
:local Script ([ /system/script/find where source~"\n# provides: capsman-rolling-upgrade\n" ]->0);
:if ([ :len $Script ] > 0) do={
/system/script/run $Script;
} else={
/caps-man/remote-cap/upgrade [ find where version!=$InstalledVersion ];
/interface/wifi/capsman/remote-cap/upgrade [ find where version!=$InstalledVersion ];
}
}
}
} on-error={ }

View file

@ -11,68 +11,75 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global CleanFilePath;
:global DownloadPackage;
:global LogPrintExit2;
:global MkDir;
:global ScriptLock;
:global WaitFullyConnected;
:do {
:local ScriptName [ :jobname ];
$ScriptLock $0;
$WaitFullyConnected;
:global CleanFilePath;
:global DownloadPackage;
:global LogPrint;
:global MkDir;
:global ScriptLock;
:global WaitFullyConnected;
:local PackagePath [ $CleanFilePath [ /interface/wifi/capsman/get package-path ] ];
:local InstalledVersion [ /system/package/update/get installed-version ];
:local Updated false;
:if ([ :len $PackagePath ] = 0) do={
$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 ([ $MkDir $PackagePath ] = false) do={
$LogPrintExit2 warning $0 ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!") true;
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
$LogPrintExit2 info $0 ("Created directory at CAPsMAN package path (" . $PackagePath . \
"). Please place your packages!") false;
}
$WaitFullyConnected;
:foreach Package in=[ /file/find where type=package \
package-version!=$InstalledVersion name~("^" . $PackagePath) ] do={
:local File [ /file/get $Package ];
:if ($File->"package-architecture" = "mips") do={
:set ($File->"package-architecture") "mipsbe";
}
:if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \
($File->"package-architecture") $PackagePath ] = true) do={
:set Updated true;
/file/remove $Package;
}
}
:local PackagePath [ $CleanFilePath [ /interface/wifi/capsman/get package-path ] ];
:local InstalledVersion [ /system/package/update/get installed-version ];
:local Updated false;
:if ([ :len [ /file/find where type=package name~("^" . $PackagePath) ] ] = 0) do={
$LogPrintExit2 info $0 ("No packages available, downloading default set.") false;
:foreach Arch in={ "arm"; "arm64" } do={
:local Packages { "arm"={ "routeros"; "wifi-qcom"; "wifi-qcom-ac" };
"arm64"={ "routeros"; "wifi-qcom" } };
:foreach Package in=($Packages->$Arch) do={
:if ([ $DownloadPackage $Package $InstalledVersion $Arch $PackagePath ] = true) do={
:set Updated true;
:if ([ :len $PackagePath ] = 0) do={
$LogPrint warning $ScriptName ("The CAPsMAN package path is not defined, can not download packages.");
:error false;
}
:if ([ :len [ /file/find where name=$PackagePath type="directory" ] ] = 0) do={
:if ([ $MkDir $PackagePath ] = false) do={
$LogPrint warning $ScriptName ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!");
:error false;
}
$LogPrint info $ScriptName ("Created directory at CAPsMAN package path (" . $PackagePath . \
"). Please place your packages!");
}
:foreach Package in=[ /file/find where type=package \
package-version!=$InstalledVersion name~("^" . $PackagePath) ] do={
:local File [ /file/get $Package ];
:if ($File->"package-architecture" = "mips") do={
:set ($File->"package-architecture") "mipsbe";
}
:if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \
($File->"package-architecture") $PackagePath ] = true) do={
:set Updated true;
/file/remove $Package;
}
}
:if ([ :len [ /file/find where type=package name~("^" . $PackagePath) ] ] = 0) do={
$LogPrint info $ScriptName ("No packages available, downloading default set.");
:foreach Arch in={ "arm"; "arm64" } do={
:local Packages { "arm"={ "routeros"; "wifi-qcom"; "wifi-qcom-ac" };
"arm64"={ "routeros"; "wifi-qcom" } };
:foreach Package in=($Packages->$Arch) do={
:if ([ $DownloadPackage $Package $InstalledVersion $Arch $PackagePath ] = true) do={
:set Updated true;
}
}
}
}
}
:if ($Updated = true) do={
:local Script ([ /system/script/find where source~"\n# provides: capsman-rolling-upgrade\n" ]->0);
:if ([ :len $Script ] > 0) do={
/system/script/run $Script;
} else={
/interface/wifi/capsman/remote-cap/upgrade [ find where version!=$InstalledVersion ];
:if ($Updated = true) do={
:local Script ([ /system/script/find where source~"\n# provides: capsman-rolling-upgrade\n" ]->0);
:if ([ :len $Script ] > 0) do={
/system/script/run $Script;
} else={
/interface/wifi/capsman/remote-cap/upgrade [ find where version!=$InstalledVersion ];
}
}
}
} on-error={ }

View file

@ -1,76 +0,0 @@
#!rsc by RouterOS
# RouterOS script: capsman-download-packages.wifiwave2
# Copyright (c) 2018-2024 Christian Hesse <mail@eworm.de>
# Michael Gisbers <michael@gisbers.de>
# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md
#
# requires RouterOS, version=7.12
#
# download and cleanup packages for CAP installation from CAPsMAN
# https://git.eworm.de/cgit/routeros-scripts/about/doc/capsman-download-packages.md
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global CleanFilePath;
:global DownloadPackage;
:global LogPrintExit2;
:global MkDir;
:global ScriptLock;
:global WaitFullyConnected;
$ScriptLock $0;
$WaitFullyConnected;
:local PackagePath [ $CleanFilePath [ /interface/wifiwave2/capsman/get package-path ] ];
:local InstalledVersion [ /system/package/update/get installed-version ];
:local Updated false;
:if ([ :len $PackagePath ] = 0) do={
$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 ([ $MkDir $PackagePath ] = false) do={
$LogPrintExit2 warning $0 ("Creating directory at CAPsMAN package path (" . \
$PackagePath . ") failed!") true;
}
$LogPrintExit2 info $0 ("Created directory at CAPsMAN package path (" . $PackagePath . \
"). Please place your packages!") false;
}
:foreach Package in=[ /file/find where type=package \
package-version!=$InstalledVersion name~("^" . $PackagePath) ] do={
:local File [ /file/get $Package ];
:if ($File->"package-architecture" = "mips") do={
:set ($File->"package-architecture") "mipsbe";
}
:if ([ $DownloadPackage ($File->"package-name") $InstalledVersion \
($File->"package-architecture") $PackagePath ] = true) do={
:set Updated true;
/file/remove $Package;
}
}
:if ([ :len [ /file/find where type=package name~("^" . $PackagePath) ] ] = 0) do={
$LogPrintExit2 info $0 ("No packages available, downloading default set.") false;
:foreach Arch in={ "arm"; "arm64" } do={
:foreach Package in={ "routeros"; "wifiwave2" } do={
:if ([ $DownloadPackage $Package $InstalledVersion $Arch $PackagePath ] = true) do={
:set Updated true;
}
}
}
}
:if ($Updated = true) do={
:local Script ([ /system/script/find where source~"\n# provides: capsman-rolling-upgrade\n" ]->0);
:if ([ :len $Script ] > 0) do={
/system/script/run $Script;
} else={
/interface/wifiwave2/capsman/remote-cap/upgrade [ find where version!=$InstalledVersion ];
}
}

View file

@ -12,30 +12,35 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global LogPrintExit2;
:global ScriptLock;
:do {
:local ScriptName [ :jobname ];
$ScriptLock $0;
:global LogPrint;
:global ScriptLock;
:local InstalledVersion [ /system/package/update/get installed-version ];
:local RemoteCapCount [ :len [ /caps-man/remote-cap/find ] ];
:if ($RemoteCapCount > 0) do={
:local Delay (600 / $RemoteCapCount);
:if ($Delay > 120) do={ :set Delay 120; }
:foreach RemoteCap in=[ /caps-man/remote-cap/find where version!=$InstalledVersion ] do={
:local RemoteCapVal [ /caps-man/remote-cap/get $RemoteCap ];
:if ([ :len $RemoteCapVal ] > 1) do={
$LogPrintExit2 info $0 ("Starting upgrade for " . $RemoteCapVal->"name" . \
" (" . $RemoteCapVal->"identity" . ")...") false;
/caps-man/remote-cap/upgrade $RemoteCap;
} else={
$LogPrintExit2 warning $0 ("Remote CAP vanished, skipping upgrade.") false;
}
:delay ($Delay . "s");
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
}
:local InstalledVersion [ /system/package/update/get installed-version ];
:local RemoteCapCount [ :len [ /caps-man/remote-cap/find ] ];
:if ($RemoteCapCount > 0) do={
:local Delay (600 / $RemoteCapCount);
:if ($Delay > 120) do={ :set Delay 120; }
:foreach RemoteCap in=[ /caps-man/remote-cap/find where version!=$InstalledVersion ] do={
:local RemoteCapVal [ /caps-man/remote-cap/get $RemoteCap ];
:if ([ :len $RemoteCapVal ] > 1) do={
$LogPrint info $ScriptName ("Starting upgrade for " . $RemoteCapVal->"name" . \
" (" . $RemoteCapVal->"identity" . ")...");
/caps-man/remote-cap/upgrade $RemoteCap;
} else={
$LogPrint warning $ScriptName ("Remote CAP vanished, skipping upgrade.");
}
:delay ($Delay . "s");
}
}
} on-error={ }

View file

@ -13,41 +13,42 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global LogPrintExit2;
:global ScriptLock;
:do {
:local ScriptName [ :jobname ];
$ScriptLock $0;
:global LogPrint;
:global ScriptLock;
:local InstalledVersion [ /system/package/update/get installed-version ];
:local RemoteCapCount [ :len [ /caps-man/remote-cap/find ] ];
:local RemoteCapCount [ :len [ /interface/wifi/capsman/remote-cap/find ] ];
:local RemoteCapCount [ :len [ /interface/wifiwave2/capsman/remote-cap/find ] ];
:if ($RemoteCapCount > 0) do={
:local Delay (600 / $RemoteCapCount);
:if ($Delay > 120) do={ :set Delay 120; }
:foreach RemoteCap in=[ /caps-man/remote-cap/find where version!=$InstalledVersion ] do={
:foreach RemoteCap in=[ /interface/wifi/capsman/remote-cap/find where version!=$InstalledVersion ] do={
:foreach RemoteCap in=[ /interface/wifiwave2/capsman/remote-cap/find where version!=$InstalledVersion ] do={
:local RemoteCapVal [ /caps-man/remote-cap/get $RemoteCap ];
:local RemoteCapVal [ /interface/wifi/capsman/remote-cap/get $RemoteCap ];
:local RemoteCapVal [ /interface/wifiwave2/capsman/remote-cap/get $RemoteCap ];
:if ([ :len $RemoteCapVal ] > 1) do={
# NOT /caps-man/ #
:set ($RemoteCapVal->"name") ($RemoteCapVal->"common-name");
# NOT /caps-man/ #
$LogPrintExit2 info $0 ("Starting upgrade for " . $RemoteCapVal->"name" . \
" (" . $RemoteCapVal->"identity" . ")...") false;
/caps-man/remote-cap/upgrade $RemoteCap;
/interface/wifi/capsman/remote-cap/upgrade $RemoteCap;
/interface/wifiwave2/capsman/remote-cap/upgrade $RemoteCap;
} else={
$LogPrintExit2 warning $0 ("Remote CAP vanished, skipping upgrade.") false;
}
:delay ($Delay . "s");
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
}
:local InstalledVersion [ /system/package/update/get installed-version ];
:local RemoteCapCount [ :len [ /caps-man/remote-cap/find ] ];
:local RemoteCapCount [ :len [ /interface/wifi/capsman/remote-cap/find ] ];
:if ($RemoteCapCount > 0) do={
:local Delay (600 / $RemoteCapCount);
:if ($Delay > 120) do={ :set Delay 120; }
:foreach RemoteCap in=[ /caps-man/remote-cap/find where version!=$InstalledVersion ] do={
:foreach RemoteCap in=[ /interface/wifi/capsman/remote-cap/find where version!=$InstalledVersion ] do={
:local RemoteCapVal [ /caps-man/remote-cap/get $RemoteCap ];
:local RemoteCapVal [ /interface/wifi/capsman/remote-cap/get $RemoteCap ];
:if ([ :len $RemoteCapVal ] > 1) do={
# NOT /caps-man/ #
:set ($RemoteCapVal->"name") ($RemoteCapVal->"common-name");
# NOT /caps-man/ #
$LogPrint info $ScriptName ("Starting upgrade for " . $RemoteCapVal->"name" . \
" (" . $RemoteCapVal->"identity" . ")...");
/caps-man/remote-cap/upgrade $RemoteCap;
/interface/wifi/capsman/remote-cap/upgrade $RemoteCap;
} else={
$LogPrint warning $ScriptName ("Remote CAP vanished, skipping upgrade.");
}
:delay ($Delay . "s");
}
}
} on-error={ }

View file

@ -12,31 +12,36 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global LogPrintExit2;
:global ScriptLock;
:do {
:local ScriptName [ :jobname ];
$ScriptLock $0;
:global LogPrint;
:global ScriptLock;
:local InstalledVersion [ /system/package/update/get installed-version ];
:local RemoteCapCount [ :len [ /interface/wifi/capsman/remote-cap/find ] ];
:if ($RemoteCapCount > 0) do={
:local Delay (600 / $RemoteCapCount);
:if ($Delay > 120) do={ :set Delay 120; }
:foreach RemoteCap in=[ /interface/wifi/capsman/remote-cap/find where version!=$InstalledVersion ] do={
:local RemoteCapVal [ /interface/wifi/capsman/remote-cap/get $RemoteCap ];
:if ([ :len $RemoteCapVal ] > 1) do={
:set ($RemoteCapVal->"name") ($RemoteCapVal->"common-name");
$LogPrintExit2 info $0 ("Starting upgrade for " . $RemoteCapVal->"name" . \
" (" . $RemoteCapVal->"identity" . ")...") false;
/interface/wifi/capsman/remote-cap/upgrade $RemoteCap;
} else={
$LogPrintExit2 warning $0 ("Remote CAP vanished, skipping upgrade.") false;
}
:delay ($Delay . "s");
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
}
:local InstalledVersion [ /system/package/update/get installed-version ];
:local RemoteCapCount [ :len [ /interface/wifi/capsman/remote-cap/find ] ];
:if ($RemoteCapCount > 0) do={
:local Delay (600 / $RemoteCapCount);
:if ($Delay > 120) do={ :set Delay 120; }
:foreach RemoteCap in=[ /interface/wifi/capsman/remote-cap/find where version!=$InstalledVersion ] do={
:local RemoteCapVal [ /interface/wifi/capsman/remote-cap/get $RemoteCap ];
:if ([ :len $RemoteCapVal ] > 1) do={
:set ($RemoteCapVal->"name") ($RemoteCapVal->"common-name");
$LogPrint info $ScriptName ("Starting upgrade for " . $RemoteCapVal->"name" . \
" (" . $RemoteCapVal->"identity" . ")...");
/interface/wifi/capsman/remote-cap/upgrade $RemoteCap;
} else={
$LogPrint warning $ScriptName ("Remote CAP vanished, skipping upgrade.");
}
:delay ($Delay . "s");
}
}
} on-error={ }

View file

@ -1,42 +0,0 @@
#!rsc by RouterOS
# RouterOS script: capsman-rolling-upgrade.wifiwave2
# Copyright (c) 2018-2024 Christian Hesse <mail@eworm.de>
# Michael Gisbers <michael@gisbers.de>
# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md
#
# provides: capsman-rolling-upgrade
# requires RouterOS, version=7.12
#
# upgrade CAPs one after another
# https://git.eworm.de/cgit/routeros-scripts/about/doc/capsman-rolling-upgrade.md
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global LogPrintExit2;
:global ScriptLock;
$ScriptLock $0;
:local InstalledVersion [ /system/package/update/get installed-version ];
:local RemoteCapCount [ :len [ /interface/wifiwave2/capsman/remote-cap/find ] ];
:if ($RemoteCapCount > 0) do={
:local Delay (600 / $RemoteCapCount);
:if ($Delay > 120) do={ :set Delay 120; }
:foreach RemoteCap in=[ /interface/wifiwave2/capsman/remote-cap/find where version!=$InstalledVersion ] do={
:local RemoteCapVal [ /interface/wifiwave2/capsman/remote-cap/get $RemoteCap ];
:if ([ :len $RemoteCapVal ] > 1) do={
:set ($RemoteCapVal->"name") ($RemoteCapVal->"common-name");
$LogPrintExit2 info $0 ("Starting upgrade for " . $RemoteCapVal->"name" . \
" (" . $RemoteCapVal->"identity" . ")...") false;
/interface/wifiwave2/capsman/remote-cap/upgrade $RemoteCap;
} else={
$LogPrintExit2 warning $0 ("Remote CAP vanished, skipping upgrade.") false;
}
:delay ($Delay . "s");
}
}

View file

@ -8,36 +8,41 @@
# renew locally issued certificates
# https://git.eworm.de/cgit/routeros-scripts/about/doc/certificate-renew-issued.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global CertIssuedExportPass;
:do {
:local ScriptName [ :jobname ];
:global LogPrintExit2;
:global MkDir;
:global ScriptLock;
:global CertIssuedExportPass;
$ScriptLock $0;
:global LogPrint;
:global MkDir;
:global ScriptLock;
:foreach Cert in=[ /certificate/find where issued expires-after<3w ] do={
:local CertVal [ /certificate/get $Cert ];
/certificate/issued-revoke $Cert;
/certificate/set name=($CertVal->"name" . "-revoked-" . [ /system/clock/get date ]) $Cert;
/certificate/add name=($CertVal->"name") common-name=($CertVal->"common-name") \
key-usage=($CertVal->"key-usage") subject-alt-name=($CertVal->"subject-alt-name");
/certificate/sign ($CertVal->"name") ca=($CertVal->"ca");
:if ([ :typeof ($CertIssuedExportPass->($CertVal->"common-name")) ] = "str") do={
:if ([ $MkDir "cert-issued" ] = true) do={
/certificate/export-certificate ($CertVal->"name") type=pkcs12 \
file-name=("cert-issued/" . $CertVal->"common-name") \
export-passphrase=($CertIssuedExportPass->($CertVal->"common-name"));
$LogPrintExit2 info $0 ("Issued a new certificate for \"" . $CertVal->"common-name" . \
"\", exported to \"cert-issued/" . $CertVal->"common-name" . ".p12\".") false;
} else={
$LogPrintExit2 warning $0 ("Failed creating directory, not exporting certificate.") false;
}
} else={
$LogPrintExit2 info $0 ("Issued a new certificate for \"" . $CertVal->"common-name" . "\".") false;
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
}
:foreach Cert in=[ /certificate/find where issued expires-after<3w ] do={
:local CertVal [ /certificate/get $Cert ];
/certificate/issued-revoke $Cert;
/certificate/set name=($CertVal->"name" . "-revoked-" . [ /system/clock/get date ]) $Cert;
/certificate/add name=($CertVal->"name") common-name=($CertVal->"common-name") \
key-usage=($CertVal->"key-usage") subject-alt-name=($CertVal->"subject-alt-name");
/certificate/sign ($CertVal->"name") ca=($CertVal->"ca");
:if ([ :typeof ($CertIssuedExportPass->($CertVal->"common-name")) ] = "str") do={
:if ([ $MkDir "cert-issued" ] = true) do={
/certificate/export-certificate ($CertVal->"name") type=pkcs12 \
file-name=("cert-issued/" . $CertVal->"common-name") \
export-passphrase=($CertIssuedExportPass->($CertVal->"common-name"));
$LogPrint info $ScriptName ("Issued a new certificate for \"" . $CertVal->"common-name" . \
"\", exported to \"cert-issued/" . $CertVal->"common-name" . ".p12\".");
} else={
$LogPrint warning $ScriptName ("Failed creating directory, not exporting certificate.");
}
} else={
$LogPrint info $ScriptName ("Issued a new certificate for \"" . $CertVal->"common-name" . "\".");
}
}
} on-error={ }

View file

@ -8,202 +8,214 @@
# check for certificate validity
# https://git.eworm.de/cgit/routeros-scripts/about/doc/check-certificates.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global CertRenewTime;
:global CertRenewUrl;
:global CertWarnTime;
:global Identity;
:global CertificateAvailable
:global EscapeForRegEx;
:global IfThenElse;
:global LogPrintExit2;
:global ParseKeyValueStore;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global UrlEncode;
:global WaitFullyConnected;
:local CheckCertificatesDownloadImport do={
:local Name [ :tostr $1 ];
:do {
:local ScriptName [ :jobname ];
:global CertRenewTime;
:global CertRenewUrl;
:global CertRenewPass;
:global CertWarnTime;
:global Identity;
:global CertificateNameByCN;
:global CertificateAvailable
:global EscapeForRegEx;
:global FetchUserAgent;
:global LogPrintExit2;
:global UrlEncode;
:global WaitForFile;
:local Return false;
:foreach Type in={ ".pem"; ".p12" } do={
:local CertFileName ([ $UrlEncode $Name ] . $Type);
:do {
/tool/fetch check-certificate=yes-without-crl http-header-field=({ $FetchUserAgent }) \
($CertRenewUrl . $CertFileName) dst-path=$CertFileName as-value;
$WaitForFile $CertFileName;
:local DecryptionFailed true;
:foreach PassPhrase in=$CertRenewPass do={
:local Result [ /certificate/import file-name=$CertFileName passphrase=$PassPhrase as-value ];
:if ($Result->"decryption-failures" = 0) do={
:set DecryptionFailed false;
}
}
/file/remove [ find where name=$CertFileName ];
:if ($DecryptionFailed = true) do={
$LogPrintExit2 warning $0 ("Decryption failed for certificate file '" . $CertFileName . "'.") false;
}
:foreach CertInChain in=[ /certificate/find where name~("^" . [ $EscapeForRegEx $CertFileName ] . "_[0-9]+\$") \
common-name!=$Name !(subject-alt-name~("(^|\\W)(DNS|IP):" . [ $EscapeForRegEx $Name ] . "(\\W|\$)")) !(common-name=[]) ] do={
$CertificateNameByCN [ /certificate/get $CertInChain common-name ];
}
:set Return true;
} on-error={
$LogPrintExit2 debug $0 ("Could not download certificate file '" . $CertFileName . "'.") false;
}
}
:return $Return;
}
:local FormatInfo do={
:local Cert $1;
:global FormatLine;
:global FormatMultiLines;
:global IfThenElse;
:global LogPrint;
:global ParseKeyValueStore;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global UrlEncode;
:global WaitFullyConnected;
:local FormatExpire do={
:global CharacterReplace;
:return [ $CharacterReplace [ $CharacterReplace [ :tostr $1 ] "w" "w " ] "d" "d " ];
:local CheckCertificatesDownloadImport do={
:local Name [ :tostr $1 ];
:global CertRenewUrl;
:global CertRenewPass;
:global CertificateNameByCN;
:global EscapeForRegEx;
:global FetchUserAgent;
:global LogPrint;
:global UrlEncode;
:global WaitForFile;
:local Return false;
:foreach Type in={ ".pem"; ".p12" } do={
:local CertFileName ([ $UrlEncode $Name ] . $Type);
:do {
/tool/fetch check-certificate=yes-without-crl http-header-field=({ $FetchUserAgent }) \
($CertRenewUrl . $CertFileName) dst-path=$CertFileName as-value;
$WaitForFile $CertFileName;
:local DecryptionFailed true;
:foreach PassPhrase in=$CertRenewPass do={
:local Result [ /certificate/import file-name=$CertFileName passphrase=$PassPhrase as-value ];
:if ($Result->"decryption-failures" = 0) do={
:set DecryptionFailed false;
}
}
/file/remove [ find where name=$CertFileName ];
:if ($DecryptionFailed = true) do={
$LogPrint warning $0 ("Decryption failed for certificate file '" . $CertFileName . "'.");
}
:foreach CertInChain in=[ /certificate/find where name~("^" . [ $EscapeForRegEx $CertFileName ] . "_[0-9]+\$") \
common-name!=$Name !(subject-alt-name~("(^|\\W)(DNS|IP):" . [ $EscapeForRegEx $Name ] . "(\\W|\$)")) !(common-name=[]) ] do={
$CertificateNameByCN [ /certificate/get $CertInChain common-name ];
}
:set Return true;
} on-error={
$LogPrint debug $0 ("Could not download certificate file '" . $CertFileName . "'.");
}
}
:return $Return;
}
:local FormatCertChain do={
:local FormatInfo do={
:local Cert $1;
:global EitherOr;
:global ParseKeyValueStore;
:global FormatLine;
:global FormatMultiLines;
:global IfThenElse;
:local FormatExpire do={
:global CharacterReplace;
:return [ $CharacterReplace [ $CharacterReplace [ :tostr $1 ] "w" "w " ] "d" "d " ];
}
:local FormatCertChain do={
:local Cert $1;
:global EitherOr;
:global ParseKeyValueStore;
:local CertVal [ /certificate/get $Cert ];
:if ([ :typeof ($CertVal->"issuer") ] = "nothing") do={
:return "self-signed";
}
:local Return "";
:for I from=0 to=5 do={
:set Return ($Return . [ $EitherOr ([ $ParseKeyValueStore ($CertVal->"issuer") ]->"CN") \
([ $ParseKeyValueStore (($CertVal->"issuer")->0) ]->"CN") ]);
:set CertVal [ /certificate/get [ find where skid=($CertVal->"akid") ] ];
:if (($CertVal->"akid") = "" || ($CertVal->"akid") = ($CertVal->"skid")) do={
:return $Return;
}
:set Return ($Return . " -> ");
}
:return ($Return . "...");
}
:local CertVal [ /certificate/get $Cert ];
:local Return "";
:for I from=0 to=5 do={
:set Return ($Return . [ $EitherOr ([ $ParseKeyValueStore ($CertVal->"issuer") ]->"CN") \
([ $ParseKeyValueStore (($CertVal->"issuer")->0) ]->"CN") ]);
:set CertVal [ /certificate/get [ find where skid=($CertVal->"akid") ] ];
:if (($CertVal->"akid") = "" || ($CertVal->"akid") = ($CertVal->"skid")) do={
:return $Return;
}
:set Return ($Return . " -> ");
}
:return ($Return . "...");
:return ( \
[ $FormatLine "Name" ($CertVal->"name") ] . "\n" . \
[ $IfThenElse ([ :len ($CertVal->"common-name") ] > 0) ([ $FormatLine "CommonName" ($CertVal->"common-name") ] . "\n") ] . \
[ $IfThenElse ([ :len ($CertVal->"subject-alt-name") ] > 0) ([ $FormatMultiLines "SubjectAltNames" ($CertVal->"subject-alt-name") ] . "\n") ] . \
[ $FormatLine "Private key" [ $IfThenElse (($CertVal->"private-key") = true) "available" "missing" ] ] . "\n" . \
[ $FormatLine "Fingerprint" ($CertVal->"fingerprint") ] . "\n" . \
[ $IfThenElse ([ :len ($CertVal->"ca") ] > 0) [ $FormatLine "Issuer" ($CertVal->"ca") ] [ $FormatLine "Issuer chain" [ $FormatCertChain $Cert ] ] ] . "\n" . \
"Validity:\n" . \
[ $FormatLine " from" ($CertVal->"invalid-before") ] . "\n" . \
[ $FormatLine " to" ($CertVal->"invalid-after") ] . "\n" . \
[ $FormatLine "Expires in" [ $IfThenElse (($CertVal->"expired") = true) "expired" [ $FormatExpire ($CertVal->"expires-after") ] ] ]);
}
:local CertVal [ /certificate/get $Cert ];
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
$WaitFullyConnected;
:return ( \
[ $FormatLine "Name" ($CertVal->"name") ] . "\n" . \
[ $IfThenElse ([ :len ($CertVal->"common-name") ] > 0) ([ $FormatLine "CommonName" ($CertVal->"common-name") ] . "\n") ] . \
[ $IfThenElse ([ :len ($CertVal->"subject-alt-name") ] > 0) ([ $FormatMultiLines "SubjectAltNames" ($CertVal->"subject-alt-name") ] . "\n") ] . \
[ $FormatLine "Private key" [ $IfThenElse (($CertVal->"private-key") = true) "available" "missing" ] ] . "\n" . \
[ $FormatLine "Fingerprint" ($CertVal->"fingerprint") ] . "\n" . \
[ $IfThenElse ([ :len ($CertVal->"ca") ] > 0) [ $FormatLine "Issuer" ($CertVal->"ca") ] [ $FormatLine "Issuer chain" [ $FormatCertChain $Cert ] ] ] . "\n" . \
"Validity:\n" . \
[ $FormatLine " from" ($CertVal->"invalid-before") ] . "\n" . \
[ $FormatLine " to" ($CertVal->"invalid-after") ] . "\n" . \
[ $FormatLine "Expires in" [ $IfThenElse (($CertVal->"expired") = true) "expired" [ $FormatExpire ($CertVal->"expires-after") ] ] ]);
}
:foreach Cert in=[ /certificate/find where !revoked !ca !scep-url expires-after<$CertRenewTime ] do={
:local CertVal [ /certificate/get $Cert ];
:local CertNew;
:local LastName;
$ScriptLock $0;
$WaitFullyConnected;
:foreach Cert in=[ /certificate/find where !revoked !ca !scep-url expires-after<$CertRenewTime ] do={
:local CertVal [ /certificate/get $Cert ];
:local CertNew;
:local LastName;
:do {
:if ([ :len $CertRenewUrl ] = 0) do={
$LogPrintExit2 info $0 ("No CertRenewUrl given.") true;
}
$LogPrintExit2 info $0 ("Attempting to renew certificate '" . ($CertVal->"name") . "'.") false;
:local ImportSuccess false;
:set LastName ($CertVal->"common-name");
:set ImportSuccess [ $CheckCertificatesDownloadImport $LastName ];
:foreach SAN in=($CertVal->"subject-alt-name") do={
:if ($ImportSuccess = false) do={
:set LastName [ :pick $SAN ([ :find $SAN ":" ] + 1) [ :len $SAN ] ];
:set ImportSuccess [ $CheckCertificatesDownloadImport $LastName ];
:do {
:if ([ :len $CertRenewUrl ] = 0) do={
$LogPrint info $ScriptName ("No CertRenewUrl given.");
:error false;
}
}
$LogPrint info $ScriptName ("Attempting to renew certificate '" . ($CertVal->"name") . "'.");
:if ([ :len ($CertVal->"fingerprint") ] > 0 && $CertVal->"fingerprint" != [ /certificate/get $Cert fingerprint ]) do={
$LogPrintExit2 debug $0 ("Certificate '" . $CertVal->"name" . "' was updated in place.") false;
:set CertVal [ /certificate/get $Cert ];
:local ImportSuccess false;
:set LastName ($CertVal->"common-name");
:set ImportSuccess [ $CheckCertificatesDownloadImport $LastName ];
:foreach SAN in=($CertVal->"subject-alt-name") do={
:if ($ImportSuccess = false) do={
:set LastName [ :pick $SAN ([ :find $SAN ":" ] + 1) [ :len $SAN ] ];
:set ImportSuccess [ $CheckCertificatesDownloadImport $LastName ];
}
}
:if ($ImportSuccess = false) do={ :error false; }
:if ([ :len ($CertVal->"fingerprint") ] > 0 && $CertVal->"fingerprint" != [ /certificate/get $Cert fingerprint ]) do={
$LogPrint debug $ScriptName ("Certificate '" . $CertVal->"name" . "' was updated in place.");
:set CertVal [ /certificate/get $Cert ];
} else={
$LogPrint debug $ScriptName ("Certificate '" . $CertVal->"name" . "' was not updated, but replaced.");
:set CertNew [ /certificate/find where name~("^" . [ $EscapeForRegEx [ $UrlEncode $LastName ] ] . "\\.(p12|pem)_[0-9]+\$") \
(common-name=($CertVal->"common-name") or subject-alt-name~("(^|\\W)(DNS|IP):" . [ $EscapeForRegEx $LastName ] . "(\\W|\$)")) \
fingerprint!=[ :tostr ($CertVal->"fingerprint") ] expires-after>$CertRenewTime ];
:local CertNewVal [ /certificate/get $CertNew ];
:if ([ $CertificateAvailable ([ $ParseKeyValueStore ($CertNewVal->"issuer") ]->"CN") ] = false) do={
$LogPrint warning $ScriptName ("The certificate chain is not available!");
}
:if (($CertVal->"private-key") = true && ($CertVal->"private-key") != ($CertNewVal->"private-key")) do={
/certificate/remove $CertNew;
$LogPrint warning $ScriptName ("Old certificate '" . ($CertVal->"name") . "' has a private key, new certificate does not. Aborting renew.");
:error false;
}
/ip/service/set certificate=($CertNewVal->"name") [ find where certificate=($CertVal->"name") ];
/ip/ipsec/identity/set certificate=($CertNewVal->"name") [ find where certificate=($CertVal->"name") ];
/ip/ipsec/identity/set remote-certificate=($CertNewVal->"name") [ find where remote-certificate=($CertVal->"name") ];
/ip/hotspot/profile/set ssl-certificate=($CertNewVal->"name") [ find where ssl-certificate=($CertVal->"name") ];
/certificate/remove $Cert;
/certificate/set $CertNew name=($CertVal->"name");
:set CertNewVal;
:set CertVal [ /certificate/get $CertNew ];
}
$SendNotification2 ({ origin=$ScriptName; silent=true; \
subject=([ $SymbolForNotification "lock-with-ink-pen" ] . "Certificate renewed: " . ($CertVal->"name")); \
message=("A certificate on " . $Identity . " has been renewed.\n\n" . [ $FormatInfo $CertNew ]) });
$LogPrint info $ScriptName ("The certificate '" . ($CertVal->"name") . "' has been renewed.");
} on-error={
$LogPrint debug $ScriptName ("Could not renew certificate '" . ($CertVal->"name") . "'.");
}
}
:foreach Cert in=[ /certificate/find where !revoked !scep-url !(expires-after=[]) \
expires-after<$CertWarnTime !(fingerprint=[]) ] do={
:local CertVal [ /certificate/get $Cert ];
:if ([ :len [ /certificate/scep-server/find where ca-cert=($CertVal->"ca") ] ] > 0) do={
$LogPrint debug $ScriptName ("Certificate '" . ($CertVal->"name") . "' is handled by SCEP, skipping.");
} else={
$LogPrintExit2 debug $0 ("Certificate '" . $CertVal->"name" . "' was not updated, but replaced.") false;
:local State [ $IfThenElse (($CertVal->"expired") = true) "expired" "is about to expire" ];
:set CertNew [ /certificate/find where name~("^" . [ $EscapeForRegEx [ $UrlEncode $LastName ] ] . "\\.(p12|pem)_[0-9]+\$") \
(common-name=($CertVal->"common-name") or subject-alt-name~("(^|\\W)(DNS|IP):" . [ $EscapeForRegEx $LastName ] . "(\\W|\$)")) \
fingerprint!=[ :tostr ($CertVal->"fingerprint") ] expires-after>$CertRenewTime ];
:local CertNewVal [ /certificate/get $CertNew ];
:if ([ $CertificateAvailable ([ $ParseKeyValueStore ($CertNewVal->"issuer") ]->"CN") ] = false) do={
$LogPrintExit2 warning $0 ("The certificate chain is not available!") false;
}
:if (($CertVal->"private-key") = true && ($CertVal->"private-key") != ($CertNewVal->"private-key")) do={
/certificate/remove $CertNew;
$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/ipsec/identity/set certificate=($CertNewVal->"name") [ find where certificate=($CertVal->"name") ];
/ip/ipsec/identity/set remote-certificate=($CertNewVal->"name") [ find where remote-certificate=($CertVal->"name") ];
/ip/hotspot/profile/set ssl-certificate=($CertNewVal->"name") [ find where ssl-certificate=($CertVal->"name") ];
/certificate/remove $Cert;
/certificate/set $CertNew name=($CertVal->"name");
:set CertNewVal;
:set CertVal [ /certificate/get $CertNew ];
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "warning-sign" ] . "Certificate warning: " . ($CertVal->"name")); \
message=("A certificate on " . $Identity . " " . $State . ".\n\n" . [ $FormatInfo $Cert ]) });
$LogPrint info $ScriptName ("The certificate '" . ($CertVal->"name") . "' " . $State . \
", it is invalid after " . ($CertVal->"invalid-after") . ".");
}
$SendNotification2 ({ origin=$0; silent=true; \
subject=([ $SymbolForNotification "lock-with-ink-pen" ] . "Certificate renewed: " . ($CertVal->"name")); \
message=("A certificate on " . $Identity . " has been renewed.\n\n" . [ $FormatInfo $CertNew ]) });
$LogPrintExit2 info $0 ("The certificate '" . ($CertVal->"name") . "' has been renewed.") false;
} on-error={
$LogPrintExit2 debug $0 ("Could not renew certificate '" . ($CertVal->"name") . "'.") false;
}
}
:foreach Cert in=[ /certificate/find where !revoked !scep-url !(expires-after=[]) \
expires-after<$CertWarnTime !(fingerprint=[]) ] do={
:local CertVal [ /certificate/get $Cert ];
: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;
} else={
:local State [ $IfThenElse (($CertVal->"expired") = true) "expired" "is about to expire" ];
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "warning-sign" ] . "Certificate warning: " . ($CertVal->"name")); \
message=("A certificate on " . $Identity . " " . $State . ".\n\n" . [ $FormatInfo $Cert ]) });
$LogPrintExit2 info $0 ("The certificate '" . ($CertVal->"name") . "' " . $State . \
", it is invalid after " . ($CertVal->"invalid-after") . ".") false;
}
}
} on-error={ }

View file

@ -8,165 +8,171 @@
# check for RouterOS health state
# https://git.eworm.de/cgit/routeros-scripts/about/doc/check-health.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global CheckHealthCPUUtilization;
:global CheckHealthCPUUtilizationNotified;
:global CheckHealthLast;
:global CheckHealthRAMUtilizationNotified;
:global CheckHealthTemperature;
:global CheckHealthTemperatureDeviation;
:global CheckHealthTemperatureNotified;
:global CheckHealthVoltageLow;
:global CheckHealthVoltagePercent;
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global FormatLine;
:global HumanReadableNum;
:global IfThenElse;
:global LogPrintExit2;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global CheckHealthCPUUtilization;
:global CheckHealthCPUUtilizationNotified;
:global CheckHealthLast;
:global CheckHealthRAMUtilizationNotified;
:global CheckHealthTemperature;
:global CheckHealthTemperatureDeviation;
:global CheckHealthTemperatureNotified;
:global CheckHealthVoltageLow;
:global CheckHealthVoltagePercent;
:global Identity;
:local TempToNum do={
:global CharacterReplace;
:local T [ :toarray [ $CharacterReplace $1 "." "," ] ];
:return ($T->0 * 10 + $T->1);
}
:global FormatLine;
:global HumanReadableNum;
:global IfThenElse;
:global LogPrint;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
$ScriptLock $0;
:local TempToNum do={
:global CharacterReplace;
:local T [ :toarray [ $CharacterReplace $1 "." "," ] ];
:return ($T->0 * 10 + $T->1);
}
:local Resource [ /system/resource/get ];
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
:set CheckHealthCPUUtilization (($CheckHealthCPUUtilization * 4 + ($Resource->"cpu-load") * 10) / 5);
:if ($CheckHealthCPUUtilization > 750 && $CheckHealthCPUUtilizationNotified != true) do={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "abacus,chart-increasing" ] . "Health warning: CPU utilization"); \
message=("The average CPU utilization on " . $Identity . " is at " . ($CheckHealthCPUUtilization / 10) . "%!") });
:set CheckHealthCPUUtilizationNotified true;
}
:if ($CheckHealthCPUUtilization < 650 && $CheckHealthCPUUtilizationNotified = true) do={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "abacus,chart-decreasing" ] . "Health recovery: CPU utilization"); \
message=("The average CPU utilization on " . $Identity . " decreased to " . ($CheckHealthCPUUtilization / 10) . "%.") });
:set CheckHealthCPUUtilizationNotified false;
}
:local Resource [ /system/resource/get ];
:local CheckHealthRAMUtilization (($Resource->"total-memory" - $Resource->"free-memory") * 100 / $Resource->"total-memory");
:if ($CheckHealthRAMUtilization >=80 && $CheckHealthRAMUtilizationNotified != true) do={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "card-file-box,chart-increasing" ] . "Health warning: RAM utilization"); \
message=("The RAM utilization on " . $Identity . " is at " . $CheckHealthRAMUtilization . "%!\n\n" . \
[ $FormatLine "total" ([ $HumanReadableNum ($Resource->"total-memory") 1024 ] . "iB") 8 ] . "\n" . \
[ $FormatLine "used" ([ $HumanReadableNum ($Resource->"total-memory" - $Resource->"free-memory") 1024 ] . "iB") 8 ] . "\n" . \
[ $FormatLine "free" ([ $HumanReadableNum ($Resource->"free-memory") 1024 ] . "iB") 8 ]) });
:set CheckHealthRAMUtilizationNotified true;
}
:if ($CheckHealthRAMUtilization < 70 && $CheckHealthRAMUtilizationNotified = true) do={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "card-file-box,chart-decreasing" ] . "Health recovery: RAM utilization"); \
message=("The RAM utilization on " . $Identity . " decreased to " . $CheckHealthRAMUtilization . "%.") });
:set CheckHealthRAMUtilizationNotified false;
}
:set CheckHealthCPUUtilization (($CheckHealthCPUUtilization * 4 + ($Resource->"cpu-load") * 10) / 5);
:if ($CheckHealthCPUUtilization > 750 && $CheckHealthCPUUtilizationNotified != true) do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "abacus,chart-increasing" ] . "Health warning: CPU utilization"); \
message=("The average CPU utilization on " . $Identity . " is at " . ($CheckHealthCPUUtilization / 10) . "%!") });
:set CheckHealthCPUUtilizationNotified true;
}
:if ($CheckHealthCPUUtilization < 650 && $CheckHealthCPUUtilizationNotified = true) do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "abacus,chart-decreasing" ] . "Health recovery: CPU utilization"); \
message=("The average CPU utilization on " . $Identity . " decreased to " . ($CheckHealthCPUUtilization / 10) . "%.") });
:set CheckHealthCPUUtilizationNotified false;
}
:if ([ :len [ /system/health/find ] ] = 0) do={
$LogPrintExit2 debug $0 ("Your device does not provide any health values.") true;
}
:local CheckHealthRAMUtilization (($Resource->"total-memory" - $Resource->"free-memory") * 100 / $Resource->"total-memory");
:if ($CheckHealthRAMUtilization >=80 && $CheckHealthRAMUtilizationNotified != true) do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "card-file-box,chart-increasing" ] . "Health warning: RAM utilization"); \
message=("The RAM utilization on " . $Identity . " is at " . $CheckHealthRAMUtilization . "%!\n\n" . \
[ $FormatLine "total" ([ $HumanReadableNum ($Resource->"total-memory") 1024 ] . "iB") 8 ] . "\n" . \
[ $FormatLine "used" ([ $HumanReadableNum ($Resource->"total-memory" - $Resource->"free-memory") 1024 ] . "iB") 8 ] . "\n" . \
[ $FormatLine "free" ([ $HumanReadableNum ($Resource->"free-memory") 1024 ] . "iB") 8 ]) });
:set CheckHealthRAMUtilizationNotified true;
}
:if ($CheckHealthRAMUtilization < 70 && $CheckHealthRAMUtilizationNotified = true) do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "card-file-box,chart-decreasing" ] . "Health recovery: RAM utilization"); \
message=("The RAM utilization on " . $Identity . " decreased to " . $CheckHealthRAMUtilization . "%.") });
:set CheckHealthRAMUtilizationNotified false;
}
:if ([ :typeof $CheckHealthLast ] != "array") do={
:set CheckHealthLast ({});
}
:if ([ :typeof $CheckHealthTemperatureNotified ] != "array") do={
:set CheckHealthTemperatureNotified ({});
}
:if ([ :len [ /system/health/find ] ] = 0) do={
$LogPrint debug $ScriptName ("Your device does not provide any health values.");
:error true;
}
:if ([ :typeof $CheckHealthLast ] != "array") do={
:set CheckHealthLast ({});
}
:if ([ :typeof $CheckHealthTemperatureNotified ] != "array") do={
:set CheckHealthTemperatureNotified ({});
}
:foreach Voltage in=[ /system/health/find where type="V" ] do={
:local Name [ /system/health/get $Voltage name ];
:local Value [ /system/health/get $Voltage value ];
:foreach Voltage in=[ /system/health/find where type="V" ] do={
:local Name [ /system/health/get $Voltage name ];
:local Value [ /system/health/get $Voltage value ];
:if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={
:local NumCurr [ $TempToNum $Value ];
:local NumLast [ $TempToNum ($CheckHealthLast->$Name) ];
:if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={
:local NumCurr [ $TempToNum $Value ];
:local NumLast [ $TempToNum ($CheckHealthLast->$Name) ];
:if ($NumLast * (100 + $CheckHealthVoltagePercent) < $NumCurr * 100 || \
$NumLast * 100 > $NumCurr * (100 + $CheckHealthVoltagePercent)) do={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification ("high-voltage-sign,chart-" . [ $IfThenElse ($NumLast < \
$NumCurr) "in" "de" ] . "creasing") ] . "Health warning: " . $Name); \
message=("The " . $Name . " on " . $Identity . " jumped more than " . $CheckHealthVoltagePercent . "%.\n\n" . \
[ $FormatLine "old value" ($CheckHealthLast->$Name . " V") 12 ] . "\n" . \
[ $FormatLine "new value" ($Value . " V") 12 ]) });
} else={
:if ($NumCurr <= $CheckHealthVoltageLow && $NumLast > $CheckHealthVoltageLow) do={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "high-voltage-sign,chart-decreasing" ] . "Health warning: Low " . $Name); \
message=("The " . $Name . " on " . $Identity . " dropped to " . $Value . " V below hard limit.") });
}
:if ($NumCurr > $CheckHealthVoltageLow && $NumLast <= $CheckHealthVoltageLow) do={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "high-voltage-sign,chart-increasing" ] . "Health recovery: Low " . $Name); \
message=("The " . $Name . " on " . $Identity . " recovered to " . $Value . " V above hard limit.") });
:if ($NumLast * (100 + $CheckHealthVoltagePercent) < $NumCurr * 100 || \
$NumLast * 100 > $NumCurr * (100 + $CheckHealthVoltagePercent)) do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification ("high-voltage-sign,chart-" . [ $IfThenElse ($NumLast < \
$NumCurr) "in" "de" ] . "creasing") ] . "Health warning: " . $Name); \
message=("The " . $Name . " on " . $Identity . " jumped more than " . $CheckHealthVoltagePercent . "%.\n\n" . \
[ $FormatLine "old value" ($CheckHealthLast->$Name . " V") 12 ] . "\n" . \
[ $FormatLine "new value" ($Value . " V") 12 ]) });
} else={
:if ($NumCurr <= $CheckHealthVoltageLow && $NumLast > $CheckHealthVoltageLow) do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "high-voltage-sign,chart-decreasing" ] . "Health warning: Low " . $Name); \
message=("The " . $Name . " on " . $Identity . " dropped to " . $Value . " V below hard limit.") });
}
:if ($NumCurr > $CheckHealthVoltageLow && $NumLast <= $CheckHealthVoltageLow) do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "high-voltage-sign,chart-increasing" ] . "Health recovery: Low " . $Name); \
message=("The " . $Name . " on " . $Identity . " recovered to " . $Value . " V above hard limit.") });
}
}
}
:set ($CheckHealthLast->$Name) $Value;
}
:set ($CheckHealthLast->$Name) $Value;
}
:foreach PSU in=[ /system/health/find where name~"^psu.*-state\$" ] do={
:local Name [ /system/health/get $PSU name ];
:local Value [ /system/health/get $PSU value ];
:foreach PSU in=[ /system/health/find where name~"^psu.*-state\$" ] do={
:local Name [ /system/health/get $PSU name ];
:local Value [ /system/health/get $PSU value ];
:if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={
:if ($CheckHealthLast->$Name = "ok" && \
$Value != "ok") do={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "cross-mark" ] . "Health warning: " . $Name); \
message=("The power supply unit '" . $Name . "' on " . $Identity . " failed!") });
}
:if ($CheckHealthLast->$Name != "ok" && \
$Value = "ok") do={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "white-heavy-check-mark" ] . "Health recovery: " . $Name); \
message=("The power supply unit '" . $Name . "' on " . $Identity . " recovered!") });
:if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={
:if ($CheckHealthLast->$Name = "ok" && \
$Value != "ok") do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "cross-mark" ] . "Health warning: " . $Name); \
message=("The power supply unit '" . $Name . "' on " . $Identity . " failed!") });
}
:if ($CheckHealthLast->$Name != "ok" && \
$Value = "ok") do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "white-heavy-check-mark" ] . "Health recovery: " . $Name); \
message=("The power supply unit '" . $Name . "' on " . $Identity . " recovered!") });
}
}
:set ($CheckHealthLast->$Name) $Value;
}
:set ($CheckHealthLast->$Name) $Value;
}
:foreach Temperature in=[ /system/health/find where type="C" ] do={
:local Name [ /system/health/get $Temperature name ];
:local Value [ /system/health/get $Temperature value ];
:foreach Temperature in=[ /system/health/find where type="C" ] do={
:local Name [ /system/health/get $Temperature name ];
:local Value [ /system/health/get $Temperature value ];
:if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={
:if ([ :typeof ($CheckHealthTemperature->$Name) ] != "num" ) do={
$LogPrintExit2 info $0 ("No threshold given for " . $Name . ", assuming 50C.") false;
:set ($CheckHealthTemperature->$Name) 50;
}
:local Validate [ /system/health/get [ find where name=$Name ] value ];
:while ($Value != $Validate) do={
:set Value $Validate;
:set Validate [ /system/health/get [ find where name=$Name ] value ];
}
:if ($Value > $CheckHealthTemperature->$Name && \
$CheckHealthTemperatureNotified->$Name != true) do={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "fire" ] . "Health warning: " . $Name); \
message=("The " . $Name . " on " . $Identity . " is above threshold: " . \
$Value . "\C2\B0" . "C") });
:set ($CheckHealthTemperatureNotified->$Name) true;
}
:if ($Value <= ($CheckHealthTemperature->$Name - $CheckHealthTemperatureDeviation) && \
$CheckHealthTemperatureNotified->$Name = true) do={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "white-heavy-check-mark" ] . "Health recovery: " . $Name); \
message=("The " . $Name . " on " . $Identity . " dropped below threshold: " . \
$Value . "\C2\B0" . "C") });
:set ($CheckHealthTemperatureNotified->$Name) false;
:if ([ :typeof ($CheckHealthLast->$Name) ] != "nothing") do={
:if ([ :typeof ($CheckHealthTemperature->$Name) ] != "num" ) do={
$LogPrint info $ScriptName ("No threshold given for " . $Name . ", assuming 50C.");
:set ($CheckHealthTemperature->$Name) 50;
}
:local Validate [ /system/health/get [ find where name=$Name ] value ];
:while ($Value != $Validate) do={
:set Value $Validate;
:set Validate [ /system/health/get [ find where name=$Name ] value ];
}
:if ($Value > $CheckHealthTemperature->$Name && \
$CheckHealthTemperatureNotified->$Name != true) do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "fire" ] . "Health warning: " . $Name); \
message=("The " . $Name . " on " . $Identity . " is above threshold: " . \
$Value . "\C2\B0" . "C") });
:set ($CheckHealthTemperatureNotified->$Name) true;
}
:if ($Value <= ($CheckHealthTemperature->$Name - $CheckHealthTemperatureDeviation) && \
$CheckHealthTemperatureNotified->$Name = true) do={
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "white-heavy-check-mark" ] . "Health recovery: " . $Name); \
message=("The " . $Name . " on " . $Identity . " dropped below threshold: " . \
$Value . "\C2\B0" . "C") });
:set ($CheckHealthTemperatureNotified->$Name) false;
}
}
:set ($CheckHealthLast->$Name) $Value;
}
:set ($CheckHealthLast->$Name) $Value;
}
} on-error={ }

View file

@ -8,91 +8,96 @@
# check for LTE firmware upgrade, send notification
# https://git.eworm.de/cgit/routeros-scripts/about/doc/check-lte-firmware-upgrade.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global SentLteFirmwareUpgradeNotification;
:do {
:local ScriptName [ :jobname ];
:global ScriptLock;
$ScriptLock $0;
:if ([ :typeof $SentLteFirmwareUpgradeNotification ] != "array") do={
:global SentLteFirmwareUpgradeNotification ({});
}
:local CheckInterface do={
:local ScriptName $1;
:local Interface $2;
:global Identity;
:global SentLteFirmwareUpgradeNotification;
:global FormatLine;
:global IfThenElse;
:global LogPrintExit2;
:global ScriptFromTerminal;
:global SendNotification2;
:global SymbolForNotification;
:global ScriptLock;
:local IntName [ /interface/lte/get $Interface name ];
:local Firmware;
:local Info;
:do {
:set Firmware [ /interface/lte/firmware-upgrade $Interface once as-value ];
:set Info [ /interface/lte/monitor $Interface once as-value ];
} on-error={
$LogPrintExit2 debug $0 ("Could not get latest LTE firmware version for interface " . \
$IntName . ".") false;
:return false;
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
:if ([ :len ($Firmware->"latest") ] = 0) do={
$LogPrintExit2 info $0 ("An empty string is not a valid version.") false;
:return false;
:if ([ :typeof $SentLteFirmwareUpgradeNotification ] != "array") do={
:global SentLteFirmwareUpgradeNotification ({});
}
:if (($Firmware->"installed") = ($Firmware->"latest")) do={
:if ([ $ScriptFromTerminal $ScriptName ] = true) do={
$LogPrintExit2 info $0 ("No firmware upgrade available for LTE interface " . $IntName . ".") false;
:local CheckInterface do={
:local ScriptName $1;
:local Interface $2;
:global Identity;
:global SentLteFirmwareUpgradeNotification;
:global FormatLine;
:global IfThenElse;
:global LogPrint;
:global ScriptFromTerminal;
:global SendNotification2;
:global SymbolForNotification;
:local IntName [ /interface/lte/get $Interface name ];
:local Firmware;
:local Info;
:do {
:set Firmware [ /interface/lte/firmware-upgrade $Interface once as-value ];
:set Info [ /interface/lte/monitor $Interface once as-value ];
} on-error={
$LogPrint debug $ScriptName ("Could not get latest LTE firmware version for interface " . \
$IntName . ".");
:return false;
}
:return true;
}
:if ([ $ScriptFromTerminal $ScriptName ] = true && \
[ :len [ /system/script/find where name="unattended-lte-firmware-upgrade" ] ] > 0) do={
:put ("Do you want to start unattended lte firmware upgrade for interface " . $IntName . "? [y/N]");
:if (([ /terminal/inkey timeout=60 ] % 32) = 25) do={
/system/script/run unattended-lte-firmware-upgrade;
$LogPrintExit2 info $0 ("Scheduled lte firmware upgrade for interface " . $IntName . "...") false;
:if ([ :len ($Firmware->"latest") ] = 0) do={
$LogPrint info $ScriptName ("An empty string is not a valid version.");
:return false;
}
:if (($Firmware->"installed") = ($Firmware->"latest")) do={
:if ([ $ScriptFromTerminal $ScriptName ] = true) do={
$LogPrint info $ScriptName ("No firmware upgrade available for LTE interface " . $IntName . ".");
}
:return true;
} else={
:put "Canceled...";
}
:if ([ $ScriptFromTerminal $ScriptName ] = true && \
[ :len [ /system/script/find where name="unattended-lte-firmware-upgrade" ] ] > 0) do={
:put ("Do you want to start unattended lte firmware upgrade for interface " . $IntName . "? [y/N]");
:if (([ /terminal/inkey timeout=60 ] % 32) = 25) do={
/system/script/run unattended-lte-firmware-upgrade;
$LogPrint info $ScriptName ("Scheduled lte firmware upgrade for interface " . $IntName . "...");
:return true;
} else={
:put "Canceled...";
}
}
:if (($SentLteFirmwareUpgradeNotification->$IntName) = ($Firmware->"latest")) do={
$LogPrint debug $ScriptName ("Already sent the LTE firmware upgrade notification for version " . \
($Firmware->"latest") . ".");
:return false;
}
$LogPrint info $ScriptName ("A new firmware version " . ($Firmware->"latest") . " is available for " . \
"LTE interface " . $IntName . ".");
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "sparkles" ] . "LTE firmware upgrade"); \
message=("A new firmware version " . ($Firmware->"latest") . " is available for " . \
"LTE interface " . $IntName . " on " . $Identity . ".\n\n" . \
[ $IfThenElse ([ :len ($Info->"manufacturer") ] > 0) ([ $FormatLine "Manufacturer" ($Info->"manufacturer") ] . "\n") ] . \
[ $IfThenElse ([ :len ($Info->"model") ] > 0) ([ $FormatLine "Model" ($Info->"model") ] . "\n") ] . \
[ $IfThenElse ([ :len ($Info->"revision") ] > 0) ([ $FormatLine "Revision" ($Info->"revision") ] . "\n") ] . \
"Firmware version:\n" . \
[ $FormatLine " Installed" ($Firmware->"installed") ] . "\n" . \
[ $FormatLine " Available" ($Firmware->"latest") ]); silent=true });
:set ($SentLteFirmwareUpgradeNotification->$IntName) ($Firmware->"latest");
}
:if (($SentLteFirmwareUpgradeNotification->$IntName) = ($Firmware->"latest")) do={
$LogPrintExit2 debug $0 ("Already sent the LTE firmware upgrade notification for version " . \
($Firmware->"latest") . ".") false;
:return false;
:foreach Interface in=[ /interface/lte/find ] do={
$CheckInterface $ScriptName $Interface;
}
$LogPrintExit2 info $0 ("A new firmware version " . ($Firmware->"latest") . " is available for " . \
"LTE interface " . $IntName . ".") false;
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "sparkles" ] . "LTE firmware upgrade"); \
message=("A new firmware version " . ($Firmware->"latest") . " is available for " . \
"LTE interface " . $IntName . " on " . $Identity . ".\n\n" . \
[ $IfThenElse ([ :len ($Info->"manufacturer") ] > 0) ([ $FormatLine "Manufacturer" ($Info->"manufacturer") ] . "\n") ] . \
[ $IfThenElse ([ :len ($Info->"model") ] > 0) ([ $FormatLine "Model" ($Info->"model") ] . "\n") ] . \
[ $IfThenElse ([ :len ($Info->"revision") ] > 0) ([ $FormatLine "Revision" ($Info->"revision") ] . "\n") ] . \
"Firmware version:\n" . \
[ $FormatLine " Installed" ($Firmware->"installed") ] . "\n" . \
[ $FormatLine " Available" ($Firmware->"latest") ]); silent=true });
:set ($SentLteFirmwareUpgradeNotification->$IntName) ($Firmware->"latest");
}
:foreach Interface in=[ /interface/lte/find ] do={
$CheckInterface $0 $Interface;
}
} on-error={ }

View file

@ -8,149 +8,157 @@
# check for RouterOS update, send notification and/or install
# https://git.eworm.de/cgit/routeros-scripts/about/doc/check-routeros-update.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global Identity;
:global SafeUpdateAll;
:global SafeUpdateNeighbor;
:global SafeUpdateNeighborIdentity;
:global SafeUpdatePatch;
:global SafeUpdateUrl;
:global SentRouterosUpdateNotification;
:do {
:local ScriptName [ :jobname ];
:global DeviceInfo;
:global EscapeForRegEx;
:global LogPrintExit2;
:global ScriptFromTerminal;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global VersionToNum;
:global WaitFullyConnected;
:global Identity;
:global SafeUpdateAll;
:global SafeUpdateNeighbor;
:global SafeUpdateNeighborIdentity;
:global SafeUpdatePatch;
:global SafeUpdateUrl;
:global SentRouterosUpdateNotification;
:local DoUpdate do={
:if ([ :len [ /system/script/find where name="packages-update" ] ] > 0) do={
/system/script/run packages-update;
} else={
/system/package/update/install without-paging;
}
:error "Waiting for system to reboot.";
}
:global DeviceInfo;
:global EscapeForRegEx;
:global LogPrint;
:global ScriptFromTerminal;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global VersionToNum;
:global WaitFullyConnected;
$ScriptLock $0;
$WaitFullyConnected;
:if ([ :len [ /system/scheduler/find where name="_RebootForUpdate" ] ] > 0) do={
:error "A reboot for update is already scheduled.";
}
$LogPrintExit2 debug $0 ("Checking for updates...") false;
/system/package/update/check-for-updates without-paging as-value;
:local Update [ /system/package/update/get ];
:if ([ $ScriptFromTerminal $0 ] = true && ($Update->"installed-version") = ($Update->"latest-version")) do={
$LogPrintExit2 info $0 ("System is already up to date.") true;
}
:local NumInstalled [ $VersionToNum ($Update->"installed-version") ];
:local NumLatest [ $VersionToNum ($Update->"latest-version") ];
:local Link ("https://mikrotik.com/download/changelogs/" . $Update->"channel" . "-release-tree");
:if ($NumLatest < 117505792) do={
$LogPrintExit2 info $0 ("The version '" . ($Update->"latest-version") . "' is not a valid version.") true;
}
:if ($NumInstalled < $NumLatest) do={
:if ($SafeUpdateAll ~ "^YES,? ?PLEASE!?\$") do={
$LogPrintExit2 info $0 ("Installing ALL versions automatically, including " . \
$Update->"latest-version" . "...") false;
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "sparkles" ] . "RouterOS update: " . $Update->"latest-version"); \
message=("Installing ALL versions automatically, including " . $Update->"latest-version" . \
"... Updating on " . $Identity . "..."); link=$Link; silent=true });
$DoUpdate;
:local DoUpdate do={
:if ([ :len [ /system/script/find where name="packages-update" ] ] > 0) do={
/system/script/run packages-update;
} else={
/system/package/update/install without-paging;
}
:error "Waiting for system to reboot.";
}
:if ($SafeUpdatePatch = true && ($NumInstalled & 0xffff0000) = ($NumLatest & 0xffff0000)) do={
$LogPrintExit2 info $0 ("Version " . $Update->"latest-version" . " is a patch release, updating...") false;
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "sparkles" ] . "RouterOS update: " . $Update->"latest-version"); \
message=("Version " . $Update->"latest-version" . " is a patch update for " . $Update->"channel" . \
", updating on " . $Identity . "..."); link=$Link; silent=true });
$DoUpdate;
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
$WaitFullyConnected;
:if ([ :len [ /system/scheduler/find where name="_RebootForUpdate" ] ] > 0) do={
:error "A reboot for update is already scheduled.";
}
:if ($SafeUpdateNeighbor = true) do={
:local Neighbors [ /ip/neighbor/find where platform="MikroTik" identity~$SafeUpdateNeighborIdentity \
version~("^" . [ $EscapeForRegEx ($Update->"latest-version") ] . "\\b") ];
:if ([ :len $Neighbors ] > 0) do={
:local Neighbor [ /ip/neighbor/get ($Neighbors->0) identity ];
$LogPrintExit2 info $0 ("Seen a neighbor (" . $Neighbor . ") running version " . \
$Update->"latest-version" . " from " . $Update->"channel" . ", updating...") false;
$SendNotification2 ({ origin=$0; \
$LogPrint debug $ScriptName ("Checking for updates...");
/system/package/update/check-for-updates without-paging as-value;
:local Update [ /system/package/update/get ];
:if ([ $ScriptFromTerminal $ScriptName ] = true && ($Update->"installed-version") = ($Update->"latest-version")) do={
$LogPrint info $ScriptName ("System is already up to date.");
:error true;
}
:local NumInstalled [ $VersionToNum ($Update->"installed-version") ];
:local NumLatest [ $VersionToNum ($Update->"latest-version") ];
:local Link ("https://mikrotik.com/download/changelogs/" . $Update->"channel" . "-release-tree");
:if ($NumLatest < 117505792) do={
$LogPrint info $ScriptName ("The version '" . ($Update->"latest-version") . "' is not a valid version.");
:error false;
}
:if ($NumInstalled < $NumLatest) do={
:if ($SafeUpdateAll ~ "^YES,? ?PLEASE!?\$") do={
$LogPrint info $ScriptName ("Installing ALL versions automatically, including " . \
$Update->"latest-version" . "...");
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "sparkles" ] . "RouterOS update: " . $Update->"latest-version"); \
message=("Seen a neighbor (" . $Neighbor . ") running version " . $Update->"latest-version" . \
" from " . $Update->"channel" . ", updating on " . $Identity . "..."); link=$Link; silent=true });
message=("Installing ALL versions automatically, including " . $Update->"latest-version" . \
"... Updating on " . $Identity . "..."); link=$Link; silent=true });
$DoUpdate;
}
}
:if ([ :len $SafeUpdateUrl ] > 0) do={
:local Result;
:do {
:set Result [ /tool/fetch check-certificate=yes-without-crl \
($SafeUpdateUrl . $Update->"channel" . "?installed=" . $Update->"installed-version" . \
"&latest=" . $Update->"latest-version") output=user as-value ];
} on-error={
$LogPrintExit2 warning $0 ("Failed receiving safe version for " . $Update->"channel" . ".") false;
}
:if ($Result->"status" = "finished" && $Result->"data" = $Update->"latest-version") do={
$LogPrintExit2 info $0 ("Version " . $Update->"latest-version" . " is considered safe, updating...") false;
$SendNotification2 ({ origin=$0; \
:if ($SafeUpdatePatch = true && ($NumInstalled & 0xffff0000) = ($NumLatest & 0xffff0000)) do={
$LogPrint info $ScriptName ("Version " . $Update->"latest-version" . " is a patch release, updating...");
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "sparkles" ] . "RouterOS update: " . $Update->"latest-version"); \
message=("Version " . $Update->"latest-version" . " is considered safe for " . $Update->"channel" . \
message=("Version " . $Update->"latest-version" . " is a patch update for " . $Update->"channel" . \
", updating on " . $Identity . "..."); link=$Link; silent=true });
$DoUpdate;
}
}
:if ([ $ScriptFromTerminal $0 ] = true) do={
:put ("Do you want to install RouterOS version " . $Update->"latest-version" . "? [y/N]");
:if (([ /terminal/inkey timeout=60 ] % 32) = 25) do={
$DoUpdate;
} else={
:put "Canceled...";
:if ($SafeUpdateNeighbor = true) do={
:local Neighbors [ /ip/neighbor/find where platform="MikroTik" identity~$SafeUpdateNeighborIdentity \
version~("^" . [ $EscapeForRegEx ($Update->"latest-version") ] . "\\b") ];
:if ([ :len $Neighbors ] > 0) do={
:local Neighbor [ /ip/neighbor/get ($Neighbors->0) identity ];
$LogPrint info $ScriptName ("Seen a neighbor (" . $Neighbor . ") running version " . \
$Update->"latest-version" . " from " . $Update->"channel" . ", updating...");
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "sparkles" ] . "RouterOS update: " . $Update->"latest-version"); \
message=("Seen a neighbor (" . $Neighbor . ") running version " . $Update->"latest-version" . \
" from " . $Update->"channel" . ", updating on " . $Identity . "..."); link=$Link; silent=true });
$DoUpdate;
}
}
:if ([ :len $SafeUpdateUrl ] > 0) do={
:local Result;
:do {
:set Result [ /tool/fetch check-certificate=yes-without-crl \
($SafeUpdateUrl . $Update->"channel" . "?installed=" . $Update->"installed-version" . \
"&latest=" . $Update->"latest-version") output=user as-value ];
} on-error={
$LogPrint warning $ScriptName ("Failed receiving safe version for " . $Update->"channel" . ".");
}
:if ($Result->"status" = "finished" && $Result->"data" = $Update->"latest-version") do={
$LogPrint info $ScriptName ("Version " . $Update->"latest-version" . " is considered safe, updating...");
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "sparkles" ] . "RouterOS update: " . $Update->"latest-version"); \
message=("Version " . $Update->"latest-version" . " is considered safe for " . $Update->"channel" . \
", updating on " . $Identity . "..."); link=$Link; silent=true });
$DoUpdate;
}
}
:if ([ $ScriptFromTerminal $ScriptName ] = true) do={
:put ("Do you want to install RouterOS version " . $Update->"latest-version" . "? [y/N]");
:if (([ /terminal/inkey timeout=60 ] % 32) = 25) do={
$DoUpdate;
} else={
:put "Canceled...";
}
}
:if ($SentRouterosUpdateNotification = $Update->"latest-version") do={
$LogPrint info $ScriptName ("Already sent the RouterOS update notification for version " . \
$Update->"latest-version" . ".");
:error true;
}
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "sparkles" ] . "RouterOS update: " . $Update->"latest-version"); \
message=("A new RouterOS version " . ($Update->"latest-version") . \
" is available for " . $Identity . ".\n\n" . \
[ $DeviceInfo ]); link=$Link; silent=true });
:set SentRouterosUpdateNotification ($Update->"latest-version");
}
:if ($SentRouterosUpdateNotification = $Update->"latest-version") do={
$LogPrintExit2 info $0 ("Already sent the RouterOS update notification for version " . \
$Update->"latest-version" . ".") true;
:if ($NumInstalled > $NumLatest) do={
:if ($SentRouterosUpdateNotification = $Update->"latest-version") do={
$LogPrint info $ScriptName ("Already sent the RouterOS downgrade notification for version " . \
$Update->"latest-version" . ".");
:error true;
}
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "warning-sign" ] . "RouterOS version: " . $Update->"latest-version"); \
message=("A different RouterOS version " . ($Update->"latest-version") . \
" is available for " . $Identity . ", but it is a downgrade.\n\n" . \
[ $DeviceInfo ]); link=$Link; silent=true });
$LogPrint info $ScriptName ("A different RouterOS version " . ($Update->"latest-version") . \
" is available for downgrade.");
:set SentRouterosUpdateNotification ($Update->"latest-version");
}
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "sparkles" ] . "RouterOS update: " . $Update->"latest-version"); \
message=("A new RouterOS version " . ($Update->"latest-version") . \
" is available for " . $Identity . ".\n\n" . \
[ $DeviceInfo ]); link=$Link; silent=true });
:set SentRouterosUpdateNotification ($Update->"latest-version");
}
:if ($NumInstalled > $NumLatest) do={
:if ($SentRouterosUpdateNotification = $Update->"latest-version") do={
$LogPrintExit2 info $0 ("Already sent the RouterOS downgrade notification for version " . \
$Update->"latest-version" . ".") true;
}
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "warning-sign" ] . "RouterOS version: " . $Update->"latest-version"); \
message=("A different RouterOS version " . ($Update->"latest-version") . \
" is available for " . $Identity . ", but it is a downgrade.\n\n" . \
[ $DeviceInfo ]); link=$Link; silent=true });
$LogPrintExit2 info $0 ("A different RouterOS version " . ($Update->"latest-version") . \
" is available for downgrade.") false;
:set SentRouterosUpdateNotification ($Update->"latest-version");
}
} on-error={ }

View file

@ -11,81 +11,86 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global EitherOr;
:global FormatLine;
:global FormatMultiLines;
:global GetMacVendor;
:global LogPrintExit2;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global Identity;
$ScriptLock $0 false 10;
:global EitherOr;
:global FormatLine;
:global FormatMultiLines;
:global GetMacVendor;
:global LogPrint;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:if ([ :len [ /caps-man/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
/caps-man/access-list/add comment="--- collected above ---" disabled=yes;
$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);
:foreach Reg in=[ /caps-man/registration-table/find ] do={
:local RegVal;
:do {
:set RegVal [ /caps-man/registration-table/get $Reg ];
} on-error={
$LogPrintExit2 debug $0 ("Device already gone... Ignoring.") false;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:error false;
}
:if ([ :len ($RegVal->"mac-address") ] > 0) do={
:local AccessList ([ /caps-man/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
$LogPrintExit2 debug $0 ("MAC address " . $RegVal->"mac-address" . " already known: " . \
[ /caps-man/access-list/get $AccessList comment ]) false;
:if ([ :len [ /caps-man/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
/caps-man/access-list/add comment="--- collected above ---" disabled=yes;
$LogPrint warning $ScriptName ("Added disabled access-list entry with comment '--- collected above ---'.");
}
:local PlaceBefore ([ /caps-man/access-list/find where comment="--- collected above ---" disabled ]->0);
:foreach Reg in=[ /caps-man/registration-table/find ] do={
:local RegVal;
:do {
:set RegVal [ /caps-man/registration-table/get $Reg ];
} on-error={
$LogPrint debug $ScriptName ("Device already gone... Ignoring.");
}
:if ([ :len $AccessList ] = 0) do={
:local Address "no dhcp lease";
:local DnsName "no dhcp lease";
:local HostName "no dhcp lease";
:local Lease ([ /ip/dhcp-server/lease/find where active-mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0);
:if ([ :len $Lease ] > 0) do={
:set Address [ /ip/dhcp-server/lease/get $Lease active-address ];
:set HostName [ $EitherOr [ /ip/dhcp-server/lease/get $Lease host-name ] "no hostname" ];
:set DnsName "no dns name";
:local DnsRec ([ /ip/dns/static/find where address=$Address ]->0);
:if ([ :len $DnsRec ] > 0) do={
:set DnsName ({ [ /ip/dns/static/get $DnsRec name ] });
:foreach CName in=[ /ip/dns/static/find where type=CNAME cname=($DnsName->0) ] do={
:set DnsName ($DnsName, [ /ip/dns/static/get $CName name ]);
:if ([ :len ($RegVal->"mac-address") ] > 0) do={
:local AccessList ([ /caps-man/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
$LogPrint debug $ScriptName ("MAC address " . $RegVal->"mac-address" . " already known: " . \
[ /caps-man/access-list/get $AccessList comment ]);
}
:if ([ :len $AccessList ] = 0) do={
:local Address "no dhcp lease";
:local DnsName "no dhcp lease";
:local HostName "no dhcp lease";
:local Lease ([ /ip/dhcp-server/lease/find where active-mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0);
:if ([ :len $Lease ] > 0) do={
:set Address [ /ip/dhcp-server/lease/get $Lease active-address ];
:set HostName [ $EitherOr [ /ip/dhcp-server/lease/get $Lease host-name ] "no hostname" ];
:set DnsName "no dns name";
:local DnsRec ([ /ip/dns/static/find where address=$Address ]->0);
:if ([ :len $DnsRec ] > 0) do={
:set DnsName ({ [ /ip/dns/static/get $DnsRec name ] });
:foreach CName in=[ /ip/dns/static/find where type=CNAME cname=($DnsName->0) ] do={
:set DnsName ($DnsName, [ /ip/dns/static/get $CName name ]);
}
}
}
:local DateTime ([ /system/clock/get date ] . " " . [ /system/clock/get time ]);
:local Vendor [ $GetMacVendor ($RegVal->"mac-address") ];
:local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \
"first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface");
$LogPrint info $ScriptName $Message;
/caps-man/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
$SendNotification2 ({ origin=$ScriptName; \
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" . \
[ $FormatLine "Controller" $Identity ] . "\n" . \
[ $FormatLine "Interface" ($RegVal->"interface") ] . "\n" . \
[ $FormatLine "SSID" ($RegVal->"ssid") ] . "\n" . \
[ $FormatLine "MAC" ($RegVal->"mac-address") ] . "\n" . \
[ $FormatLine "Vendor" $Vendor ] . "\n" . \
[ $FormatLine "Hostname" $HostName ] . "\n" . \
[ $FormatLine "Address" $Address ] . "\n" . \
[ $FormatMultiLines "DNS name" $DnsName ] . "\n" . \
[ $FormatLine "Date" $DateTime ]) });
}
:local DateTime ([ /system/clock/get date ] . " " . [ /system/clock/get time ]);
:local Vendor [ $GetMacVendor ($RegVal->"mac-address") ];
:local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \
"first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface");
$LogPrintExit2 info $0 $Message false;
/caps-man/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
$SendNotification2 ({ origin=$0; \
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" . \
[ $FormatLine "Controller" $Identity ] . "\n" . \
[ $FormatLine "Interface" ($RegVal->"interface") ] . "\n" . \
[ $FormatLine "SSID" ($RegVal->"ssid") ] . "\n" . \
[ $FormatLine "MAC" ($RegVal->"mac-address") ] . "\n" . \
[ $FormatLine "Vendor" $Vendor ] . "\n" . \
[ $FormatLine "Hostname" $HostName ] . "\n" . \
[ $FormatLine "Address" $Address ] . "\n" . \
[ $FormatMultiLines "DNS name" $DnsName ] . "\n" . \
[ $FormatLine "Date" $DateTime ]) });
} else={
$LogPrint debug $ScriptName ("No mac address available... Ignoring.");
}
} else={
$LogPrintExit2 debug $0 ("No mac address available... Ignoring.") false;
}
}
} on-error={ }

View file

@ -11,82 +11,87 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global EitherOr;
:global FormatLine;
:global FormatMultiLines;
:global GetMacVendor;
:global LogPrintExit2;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global Identity;
$ScriptLock $0 false 10;
:global EitherOr;
:global FormatLine;
:global FormatMultiLines;
:global GetMacVendor;
:global LogPrint;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:if ([ :len [ /interface/wireless/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
/interface/wireless/access-list/add comment="--- collected above ---" disabled=yes;
$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);
:foreach Reg in=[ /interface/wireless/registration-table/find where ap=no ] do={
:local RegVal;
:do {
:set RegVal [ /interface/wireless/registration-table/get $Reg ];
} on-error={
$LogPrintExit2 debug $0 ("Device already gone... Ignoring.") false;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:error false;
}
:if ([ :len ($RegVal->"mac-address") ] > 0) do={
:local AccessList ([ /interface/wireless/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
$LogPrintExit2 debug $0 ("MAC address " . $RegVal->"mac-address" . " already known: " . \
[ /interface/wireless/access-list/get $AccessList comment ]) false;
:if ([ :len [ /interface/wireless/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
/interface/wireless/access-list/add comment="--- collected above ---" disabled=yes;
$LogPrint warning $ScriptName ("Added disabled access-list entry with comment '--- collected above ---'.");
}
:local PlaceBefore ([ /interface/wireless/access-list/find where comment="--- collected above ---" disabled ]->0);
:foreach Reg in=[ /interface/wireless/registration-table/find where ap=no ] do={
:local RegVal;
:do {
:set RegVal [ /interface/wireless/registration-table/get $Reg ];
} on-error={
$LogPrint debug $ScriptName ("Device already gone... Ignoring.");
}
:if ([ :len $AccessList ] = 0) do={
:local Address "no dhcp lease";
:local DnsName "no dhcp lease";
:local HostName "no dhcp lease";
:local Lease ([ /ip/dhcp-server/lease/find where active-mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0);
:if ([ :len $Lease ] > 0) do={
:set Address [ /ip/dhcp-server/lease/get $Lease active-address ];
:set HostName [ $EitherOr [ /ip/dhcp-server/lease/get $Lease host-name ] "no hostname" ];
:set DnsName "no dns name";
:local DnsRec ([ /ip/dns/static/find where address=$Address ]->0);
:if ([ :len $DnsRec ] > 0) do={
:set DnsName ({ [ /ip/dns/static/get $DnsRec name ] });
:foreach CName in=[ /ip/dns/static/find where type=CNAME cname=($DnsName->0) ] do={
:set DnsName ($DnsName, [ /ip/dns/static/get $CName name ]);
:if ([ :len ($RegVal->"mac-address") ] > 0) do={
:local AccessList ([ /interface/wireless/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
$LogPrint debug $ScriptName ("MAC address " . $RegVal->"mac-address" . " already known: " . \
[ /interface/wireless/access-list/get $AccessList comment ]);
}
:if ([ :len $AccessList ] = 0) do={
:local Address "no dhcp lease";
:local DnsName "no dhcp lease";
:local HostName "no dhcp lease";
:local Lease ([ /ip/dhcp-server/lease/find where active-mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0);
:if ([ :len $Lease ] > 0) do={
:set Address [ /ip/dhcp-server/lease/get $Lease active-address ];
:set HostName [ $EitherOr [ /ip/dhcp-server/lease/get $Lease host-name ] "no hostname" ];
:set DnsName "no dns name";
:local DnsRec ([ /ip/dns/static/find where address=$Address ]->0);
:if ([ :len $DnsRec ] > 0) do={
:set DnsName ({ [ /ip/dns/static/get $DnsRec name ] });
:foreach CName in=[ /ip/dns/static/find where type=CNAME cname=($DnsName->0) ] do={
:set DnsName ($DnsName, [ /ip/dns/static/get $CName name ]);
}
}
}
:set ($RegVal->"ssid") [ /interface/wireless/get [ find where name=($RegVal->"interface") ] ssid ];
:local DateTime ([ /system/clock/get date ] . " " . [ /system/clock/get time ]);
:local Vendor [ $GetMacVendor ($RegVal->"mac-address") ];
:local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \
"first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface");
$LogPrint info $ScriptName $Message;
/interface/wireless/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
$SendNotification2 ({ origin=$ScriptName; \
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" . \
[ $FormatLine "Controller" $Identity ] . "\n" . \
[ $FormatLine "Interface" ($RegVal->"interface") ] . "\n" . \
[ $FormatLine "SSID" ($RegVal->"ssid") ] . "\n" . \
[ $FormatLine "MAC" ($RegVal->"mac-address") ] . "\n" . \
[ $FormatLine "Vendor" $Vendor ] . "\n" . \
[ $FormatLine "Hostname" $HostName ] . "\n" . \
[ $FormatLine "Address" $Address ] . "\n" . \
[ $FormatMultiLines "DNS name" $DnsName ] . "\n" . \
[ $FormatLine "Date" $DateTime ]) });
}
:set ($RegVal->"ssid") [ /interface/wireless/get [ find where name=($RegVal->"interface") ] ssid ];
:local DateTime ([ /system/clock/get date ] . " " . [ /system/clock/get time ]);
:local Vendor [ $GetMacVendor ($RegVal->"mac-address") ];
:local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \
"first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface");
$LogPrintExit2 info $0 $Message false;
/interface/wireless/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
$SendNotification2 ({ origin=$0; \
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" . \
[ $FormatLine "Controller" $Identity ] . "\n" . \
[ $FormatLine "Interface" ($RegVal->"interface") ] . "\n" . \
[ $FormatLine "SSID" ($RegVal->"ssid") ] . "\n" . \
[ $FormatLine "MAC" ($RegVal->"mac-address") ] . "\n" . \
[ $FormatLine "Vendor" $Vendor ] . "\n" . \
[ $FormatLine "Hostname" $HostName ] . "\n" . \
[ $FormatLine "Address" $Address ] . "\n" . \
[ $FormatMultiLines "DNS name" $DnsName ] . "\n" . \
[ $FormatLine "Date" $DateTime ]) });
} else={
$LogPrint debug $ScriptName ("No mac address available... Ignoring.");
}
} else={
$LogPrintExit2 debug $0 ("No mac address available... Ignoring.") false;
}
}
} on-error={ }

View file

@ -12,106 +12,103 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global EitherOr;
:global FormatLine;
:global FormatMultiLines;
:global GetMacVendor;
:global LogPrintExit2;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global Identity;
$ScriptLock $0 false 10;
:global EitherOr;
:global FormatLine;
:global FormatMultiLines;
:global GetMacVendor;
:global LogPrint;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:if ([ :len [ /caps-man/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
:if ([ :len [ /interface/wifi/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
:if ([ :len [ /interface/wifiwave2/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
:if ([ :len [ /interface/wireless/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
/caps-man/access-list/add comment="--- collected above ---" disabled=yes;
/interface/wifi/access-list/add comment="--- collected above ---" disabled=yes;
/interface/wifiwave2/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;
}
:local PlaceBefore ([ /caps-man/access-list/find where comment="--- collected above ---" disabled ]->0);
:local PlaceBefore ([ /interface/wifi/access-list/find where comment="--- collected above ---" disabled ]->0);
:local PlaceBefore ([ /interface/wifiwave2/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=[ /caps-man/registration-table/find ] do={
:foreach Reg in=[ /interface/wifi/registration-table/find ] do={
:foreach Reg in=[ /interface/wifiwave2/registration-table/find ] do={
:foreach Reg in=[ /interface/wireless/registration-table/find where ap=no ] do={
:local RegVal;
:do {
:set RegVal [ /caps-man/registration-table/get $Reg ];
:set RegVal [ /interface/wifi/registration-table/get $Reg ];
:set RegVal [ /interface/wifiwave2/registration-table/get $Reg ];
:set RegVal [ /interface/wireless/registration-table/get $Reg ];
} on-error={
$LogPrintExit2 debug $0 ("Device already gone... Ignoring.") false;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:error false;
}
:if ([ :len ($RegVal->"mac-address") ] > 0) do={
:local AccessList ([ /caps-man/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:local AccessList ([ /interface/wifi/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:local AccessList ([ /interface/wifiwave2/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={
$LogPrintExit2 debug $0 ("MAC address " . $RegVal->"mac-address" . " already known: " . \
[ /caps-man/access-list/get $AccessList comment ]) false;
[ /interface/wifi/access-list/get $AccessList comment ]) false;
[ /interface/wifiwave2/access-list/get $AccessList comment ]) false;
[ /interface/wireless/access-list/get $AccessList comment ]) false;
:if ([ :len [ /caps-man/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
:if ([ :len [ /interface/wifi/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
:if ([ :len [ /interface/wireless/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
/caps-man/access-list/add comment="--- collected above ---" disabled=yes;
/interface/wifi/access-list/add comment="--- collected above ---" disabled=yes;
/interface/wireless/access-list/add comment="--- collected above ---" disabled=yes;
$LogPrint warning $ScriptName ("Added disabled access-list entry with comment '--- collected above ---'.");
}
:local PlaceBefore ([ /caps-man/access-list/find where comment="--- collected above ---" disabled ]->0);
:local PlaceBefore ([ /interface/wifi/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=[ /caps-man/registration-table/find ] do={
:foreach Reg in=[ /interface/wifi/registration-table/find ] do={
:foreach Reg in=[ /interface/wireless/registration-table/find where ap=no ] do={
:local RegVal;
:do {
:set RegVal [ /caps-man/registration-table/get $Reg ];
:set RegVal [ /interface/wifi/registration-table/get $Reg ];
:set RegVal [ /interface/wireless/registration-table/get $Reg ];
} on-error={
$LogPrint debug $ScriptName ("Device already gone... Ignoring.");
}
:if ([ :len $AccessList ] = 0) do={
:local Address "no dhcp lease";
:local DnsName "no dhcp lease";
:local HostName "no dhcp lease";
:local Lease ([ /ip/dhcp-server/lease/find where active-mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0);
:if ([ :len $Lease ] > 0) do={
:set Address [ /ip/dhcp-server/lease/get $Lease active-address ];
:set HostName [ $EitherOr [ /ip/dhcp-server/lease/get $Lease host-name ] "no hostname" ];
:set DnsName "no dns name";
:local DnsRec ([ /ip/dns/static/find where address=$Address ]->0);
:if ([ :len $DnsRec ] > 0) do={
:set DnsName ({ [ /ip/dns/static/get $DnsRec name ] });
:foreach CName in=[ /ip/dns/static/find where type=CNAME cname=($DnsName->0) ] do={
:set DnsName ($DnsName, [ /ip/dns/static/get $CName name ]);
:if ([ :len ($RegVal->"mac-address") ] > 0) do={
:local AccessList ([ /caps-man/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:local AccessList ([ /interface/wifi/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={
$LogPrint debug $ScriptName ("MAC address " . $RegVal->"mac-address" . " already known: " . \
[ /caps-man/access-list/get $AccessList comment ]);
[ /interface/wifi/access-list/get $AccessList comment ]);
[ /interface/wireless/access-list/get $AccessList comment ]);
}
:if ([ :len $AccessList ] = 0) do={
:local Address "no dhcp lease";
:local DnsName "no dhcp lease";
:local HostName "no dhcp lease";
:local Lease ([ /ip/dhcp-server/lease/find where active-mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0);
:if ([ :len $Lease ] > 0) do={
:set Address [ /ip/dhcp-server/lease/get $Lease active-address ];
:set HostName [ $EitherOr [ /ip/dhcp-server/lease/get $Lease host-name ] "no hostname" ];
:set DnsName "no dns name";
:local DnsRec ([ /ip/dns/static/find where address=$Address ]->0);
:if ([ :len $DnsRec ] > 0) do={
:set DnsName ({ [ /ip/dns/static/get $DnsRec name ] });
:foreach CName in=[ /ip/dns/static/find where type=CNAME cname=($DnsName->0) ] do={
:set DnsName ($DnsName, [ /ip/dns/static/get $CName name ]);
}
}
}
:set ($RegVal->"ssid") [ /interface/wireless/get [ find where name=($RegVal->"interface") ] ssid ];
:local DateTime ([ /system/clock/get date ] . " " . [ /system/clock/get time ]);
:local Vendor [ $GetMacVendor ($RegVal->"mac-address") ];
:local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \
"first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface");
$LogPrint info $ScriptName $Message;
/caps-man/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
/interface/wifi/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=$ScriptName; \
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" . \
[ $FormatLine "Controller" $Identity ] . "\n" . \
[ $FormatLine "Interface" ($RegVal->"interface") ] . "\n" . \
[ $FormatLine "SSID" ($RegVal->"ssid") ] . "\n" . \
[ $FormatLine "MAC" ($RegVal->"mac-address") ] . "\n" . \
[ $FormatLine "Vendor" $Vendor ] . "\n" . \
[ $FormatLine "Hostname" $HostName ] . "\n" . \
[ $FormatLine "Address" $Address ] . "\n" . \
[ $FormatMultiLines "DNS name" $DnsName ] . "\n" . \
[ $FormatLine "Date" $DateTime ]) });
}
:set ($RegVal->"ssid") [ /interface/wireless/get [ find where name=($RegVal->"interface") ] ssid ];
:local DateTime ([ /system/clock/get date ] . " " . [ /system/clock/get time ]);
:local Vendor [ $GetMacVendor ($RegVal->"mac-address") ];
:local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \
"first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface");
$LogPrintExit2 info $0 $Message false;
/caps-man/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
/interface/wifi/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
/interface/wifiwave2/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; \
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" . \
[ $FormatLine "Controller" $Identity ] . "\n" . \
[ $FormatLine "Interface" ($RegVal->"interface") ] . "\n" . \
[ $FormatLine "SSID" ($RegVal->"ssid") ] . "\n" . \
[ $FormatLine "MAC" ($RegVal->"mac-address") ] . "\n" . \
[ $FormatLine "Vendor" $Vendor ] . "\n" . \
[ $FormatLine "Hostname" $HostName ] . "\n" . \
[ $FormatLine "Address" $Address ] . "\n" . \
[ $FormatMultiLines "DNS name" $DnsName ] . "\n" . \
[ $FormatLine "Date" $DateTime ]) });
} else={
$LogPrint debug $ScriptName ("No mac address available... Ignoring.");
}
} else={
$LogPrintExit2 debug $0 ("No mac address available... Ignoring.") false;
}
}
} on-error={ }

View file

@ -11,81 +11,86 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global EitherOr;
:global FormatLine;
:global FormatMultiLines;
:global GetMacVendor;
:global LogPrintExit2;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global Identity;
$ScriptLock $0 false 10;
:global EitherOr;
:global FormatLine;
:global FormatMultiLines;
:global GetMacVendor;
:global LogPrint;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:if ([ :len [ /interface/wifi/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
/interface/wifi/access-list/add comment="--- collected above ---" disabled=yes;
$LogPrintExit2 warning $0 ("Added disabled access-list entry with comment '--- collected above ---'.") false;
}
:local PlaceBefore ([ /interface/wifi/access-list/find where comment="--- collected above ---" disabled ]->0);
:foreach Reg in=[ /interface/wifi/registration-table/find ] do={
:local RegVal;
:do {
:set RegVal [ /interface/wifi/registration-table/get $Reg ];
} on-error={
$LogPrintExit2 debug $0 ("Device already gone... Ignoring.") false;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:error false;
}
:if ([ :len ($RegVal->"mac-address") ] > 0) do={
:local AccessList ([ /interface/wifi/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
$LogPrintExit2 debug $0 ("MAC address " . $RegVal->"mac-address" . " already known: " . \
[ /interface/wifi/access-list/get $AccessList comment ]) false;
:if ([ :len [ /interface/wifi/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
/interface/wifi/access-list/add comment="--- collected above ---" disabled=yes;
$LogPrint warning $ScriptName ("Added disabled access-list entry with comment '--- collected above ---'.");
}
:local PlaceBefore ([ /interface/wifi/access-list/find where comment="--- collected above ---" disabled ]->0);
:foreach Reg in=[ /interface/wifi/registration-table/find ] do={
:local RegVal;
:do {
:set RegVal [ /interface/wifi/registration-table/get $Reg ];
} on-error={
$LogPrint debug $ScriptName ("Device already gone... Ignoring.");
}
:if ([ :len $AccessList ] = 0) do={
:local Address "no dhcp lease";
:local DnsName "no dhcp lease";
:local HostName "no dhcp lease";
:local Lease ([ /ip/dhcp-server/lease/find where active-mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0);
:if ([ :len $Lease ] > 0) do={
:set Address [ /ip/dhcp-server/lease/get $Lease active-address ];
:set HostName [ $EitherOr [ /ip/dhcp-server/lease/get $Lease host-name ] "no hostname" ];
:set DnsName "no dns name";
:local DnsRec ([ /ip/dns/static/find where address=$Address ]->0);
:if ([ :len $DnsRec ] > 0) do={
:set DnsName ({ [ /ip/dns/static/get $DnsRec name ] });
:foreach CName in=[ /ip/dns/static/find where type=CNAME cname=($DnsName->0) ] do={
:set DnsName ($DnsName, [ /ip/dns/static/get $CName name ]);
:if ([ :len ($RegVal->"mac-address") ] > 0) do={
:local AccessList ([ /interface/wifi/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
$LogPrint debug $ScriptName ("MAC address " . $RegVal->"mac-address" . " already known: " . \
[ /interface/wifi/access-list/get $AccessList comment ]);
}
:if ([ :len $AccessList ] = 0) do={
:local Address "no dhcp lease";
:local DnsName "no dhcp lease";
:local HostName "no dhcp lease";
:local Lease ([ /ip/dhcp-server/lease/find where active-mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0);
:if ([ :len $Lease ] > 0) do={
:set Address [ /ip/dhcp-server/lease/get $Lease active-address ];
:set HostName [ $EitherOr [ /ip/dhcp-server/lease/get $Lease host-name ] "no hostname" ];
:set DnsName "no dns name";
:local DnsRec ([ /ip/dns/static/find where address=$Address ]->0);
:if ([ :len $DnsRec ] > 0) do={
:set DnsName ({ [ /ip/dns/static/get $DnsRec name ] });
:foreach CName in=[ /ip/dns/static/find where type=CNAME cname=($DnsName->0) ] do={
:set DnsName ($DnsName, [ /ip/dns/static/get $CName name ]);
}
}
}
:local DateTime ([ /system/clock/get date ] . " " . [ /system/clock/get time ]);
:local Vendor [ $GetMacVendor ($RegVal->"mac-address") ];
:local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \
"first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface");
$LogPrint info $ScriptName $Message;
/interface/wifi/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
$SendNotification2 ({ origin=$ScriptName; \
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" . \
[ $FormatLine "Controller" $Identity ] . "\n" . \
[ $FormatLine "Interface" ($RegVal->"interface") ] . "\n" . \
[ $FormatLine "SSID" ($RegVal->"ssid") ] . "\n" . \
[ $FormatLine "MAC" ($RegVal->"mac-address") ] . "\n" . \
[ $FormatLine "Vendor" $Vendor ] . "\n" . \
[ $FormatLine "Hostname" $HostName ] . "\n" . \
[ $FormatLine "Address" $Address ] . "\n" . \
[ $FormatMultiLines "DNS name" $DnsName ] . "\n" . \
[ $FormatLine "Date" $DateTime ]) });
}
:local DateTime ([ /system/clock/get date ] . " " . [ /system/clock/get time ]);
:local Vendor [ $GetMacVendor ($RegVal->"mac-address") ];
:local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \
"first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface");
$LogPrintExit2 info $0 $Message false;
/interface/wifi/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
$SendNotification2 ({ origin=$0; \
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" . \
[ $FormatLine "Controller" $Identity ] . "\n" . \
[ $FormatLine "Interface" ($RegVal->"interface") ] . "\n" . \
[ $FormatLine "SSID" ($RegVal->"ssid") ] . "\n" . \
[ $FormatLine "MAC" ($RegVal->"mac-address") ] . "\n" . \
[ $FormatLine "Vendor" $Vendor ] . "\n" . \
[ $FormatLine "Hostname" $HostName ] . "\n" . \
[ $FormatLine "Address" $Address ] . "\n" . \
[ $FormatMultiLines "DNS name" $DnsName ] . "\n" . \
[ $FormatLine "Date" $DateTime ]) });
} else={
$LogPrint debug $ScriptName ("No mac address available... Ignoring.");
}
} else={
$LogPrintExit2 debug $0 ("No mac address available... Ignoring.") false;
}
}
} on-error={ }

View file

@ -1,91 +0,0 @@
#!rsc by RouterOS
# RouterOS script: collect-wireless-mac.wifiwave2
# Copyright (c) 2013-2024 Christian Hesse <mail@eworm.de>
# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md
#
# provides: lease-script, order=40
# requires RouterOS, version=7.12
#
# collect wireless mac adresses in access list
# https://git.eworm.de/cgit/routeros-scripts/about/doc/collect-wireless-mac.md
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global Identity;
:global EitherOr;
:global FormatLine;
:global FormatMultiLines;
:global GetMacVendor;
:global LogPrintExit2;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
$ScriptLock $0 false 10;
:if ([ :len [ /interface/wifiwave2/access-list/find where comment="--- collected above ---" disabled ] ] = 0) do={
/interface/wifiwave2/access-list/add comment="--- collected above ---" disabled=yes;
$LogPrintExit2 warning $0 ("Added disabled access-list entry with comment '--- collected above ---'.") false;
}
:local PlaceBefore ([ /interface/wifiwave2/access-list/find where comment="--- collected above ---" disabled ]->0);
:foreach Reg in=[ /interface/wifiwave2/registration-table/find ] do={
:local RegVal;
:do {
:set RegVal [ /interface/wifiwave2/registration-table/get $Reg ];
} on-error={
$LogPrintExit2 debug $0 ("Device already gone... Ignoring.") false;
}
:if ([ :len ($RegVal->"mac-address") ] > 0) do={
:local AccessList ([ /interface/wifiwave2/access-list/find where mac-address=($RegVal->"mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
$LogPrintExit2 debug $0 ("MAC address " . $RegVal->"mac-address" . " already known: " . \
[ /interface/wifiwave2/access-list/get $AccessList comment ]) false;
}
:if ([ :len $AccessList ] = 0) do={
:local Address "no dhcp lease";
:local DnsName "no dhcp lease";
:local HostName "no dhcp lease";
:local Lease ([ /ip/dhcp-server/lease/find where active-mac-address=($RegVal->"mac-address") dynamic=yes status=bound ]->0);
:if ([ :len $Lease ] > 0) do={
:set Address [ /ip/dhcp-server/lease/get $Lease active-address ];
:set HostName [ $EitherOr [ /ip/dhcp-server/lease/get $Lease host-name ] "no hostname" ];
:set DnsName "no dns name";
:local DnsRec ([ /ip/dns/static/find where address=$Address ]->0);
:if ([ :len $DnsRec ] > 0) do={
:set DnsName ({ [ /ip/dns/static/get $DnsRec name ] });
:foreach CName in=[ /ip/dns/static/find where type=CNAME cname=($DnsName->0) ] do={
:set DnsName ($DnsName, [ /ip/dns/static/get $CName name ]);
}
}
}
:local DateTime ([ /system/clock/get date ] . " " . [ /system/clock/get time ]);
:local Vendor [ $GetMacVendor ($RegVal->"mac-address") ];
:local Message ("MAC address " . $RegVal->"mac-address" . " (" . $Vendor . ", " . $HostName . ") " . \
"first seen on " . $DateTime . " connected to SSID " . $RegVal->"ssid" . ", interface " . $RegVal->"interface");
$LogPrintExit2 info $0 $Message false;
/interface/wifiwave2/access-list/add place-before=$PlaceBefore comment=$Message mac-address=($RegVal->"mac-address") disabled=yes;
$SendNotification2 ({ origin=$0; \
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" . \
[ $FormatLine "Controller" $Identity ] . "\n" . \
[ $FormatLine "Interface" ($RegVal->"interface") ] . "\n" . \
[ $FormatLine "SSID" ($RegVal->"ssid") ] . "\n" . \
[ $FormatLine "MAC" ($RegVal->"mac-address") ] . "\n" . \
[ $FormatLine "Vendor" $Vendor ] . "\n" . \
[ $FormatLine "Hostname" $HostName ] . "\n" . \
[ $FormatLine "Address" $Address ] . "\n" . \
[ $FormatMultiLines "DNS name" $DnsName ] . "\n" . \
[ $FormatLine "Date" $DateTime ]) });
}
} else={
$LogPrintExit2 debug $0 ("No mac address available... Ignoring.") false;
}
}

View file

@ -11,77 +11,82 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global DailyPskMatchComment;
:global DailyPskQrCodeUrl;
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global FormatLine;
:global LogPrintExit2;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global UrlEncode;
:global WaitForFile;
:global WaitFullyConnected;
:global DailyPskMatchComment;
:global DailyPskQrCodeUrl;
:global Identity;
$ScriptLock $0;
$WaitFullyConnected;
:global FormatLine;
:global LogPrint;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global UrlEncode;
:global WaitForFile;
:global WaitFullyConnected;
# return pseudo-random string for PSK
:local GeneratePSK do={
:local Date [ :tostr $1 ];
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
$WaitFullyConnected;
:global DailyPskSecrets;
# return pseudo-random string for PSK
:local GeneratePSK do={
:local Date [ :tostr $1 ];
:global ParseDate;
:global DailyPskSecrets;
:set Date [ $ParseDate $Date ];
:global ParseDate;
:local A ((14 - ($Date->"month")) / 12);
:local B (($Date->"year") - $A);
:local C (($Date->"month") + 12 * $A - 2);
:local WeekDay (7000 + ($Date->"day") + $B + ($B / 4) - ($B / 100) + ($B / 400) + ((31 * $C) / 12));
:set WeekDay ($WeekDay - (($WeekDay / 7) * 7));
:set Date [ $ParseDate $Date ];
:return (($DailyPskSecrets->0->(($Date->"day") - 1)) . \
($DailyPskSecrets->1->(($Date->"month") - 1)) . \
($DailyPskSecrets->2->$WeekDay));
}
:local A ((14 - ($Date->"month")) / 12);
:local B (($Date->"year") - $A);
:local C (($Date->"month") + 12 * $A - 2);
:local WeekDay (7000 + ($Date->"day") + $B + ($B / 4) - ($B / 100) + ($B / 400) + ((31 * $C) / 12));
:set WeekDay ($WeekDay - (($WeekDay / 7) * 7));
:local Seen ({});
:local Date [ /system/clock/get date ];
:local NewPsk [ $GeneratePSK $Date ];
:return (($DailyPskSecrets->0->(($Date->"day") - 1)) . \
($DailyPskSecrets->1->(($Date->"month") - 1)) . \
($DailyPskSecrets->2->$WeekDay));
}
:foreach AccList in=[ /caps-man/access-list/find where comment~$DailyPskMatchComment ] do={
:local SsidRegExp [ /caps-man/access-list/get $AccList ssid-regexp ];
:local Configuration ([ /caps-man/configuration/find where ssid~$SsidRegExp ]->0);
:local Ssid [ /caps-man/configuration/get $Configuration ssid ];
:local OldPsk [ /caps-man/access-list/get $AccList private-passphrase ];
:local Skip 0;
:local Seen ({});
:local Date [ /system/clock/get date ];
:local NewPsk [ $GeneratePSK $Date ];
:if ($NewPsk != $OldPsk) do={
$LogPrintExit2 info $0 ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")") false;
/caps-man/access-list/set $AccList private-passphrase=$NewPsk;
:foreach AccList in=[ /caps-man/access-list/find where comment~$DailyPskMatchComment ] do={
:local SsidRegExp [ /caps-man/access-list/get $AccList ssid-regexp ];
:local Configuration ([ /caps-man/configuration/find where ssid~$SsidRegExp ]->0);
:local Ssid [ /caps-man/configuration/get $Configuration ssid ];
:local OldPsk [ /caps-man/access-list/get $AccList private-passphrase ];
:local Skip 0;
:if ([ :len [ /caps-man/actual-interface-configuration/find where configuration.ssid=$Ssid !disabled ] ] > 0) do={
:if ($Seen->$Ssid = 1) do={
$LogPrintExit2 debug $0 ("Already sent a mail for SSID " . $Ssid . ", skipping.") false;
} else={
:local Link ($DailyPskQrCodeUrl . \
"?scale=8&level=1&ssid=" . [ $UrlEncode $Ssid ] . "&pass=" . [ $UrlEncode $NewPsk ]);
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "calendar" ] . "daily PSK " . $Ssid); \
message=("This is the daily PSK on " . $Identity . ":\n\n" . \
[ $FormatLine "SSID" $Ssid ] . "\n" . \
[ $FormatLine "PSK" $NewPsk ] . "\n" . \
[ $FormatLine "Date" $Date ] . "\n\n" . \
"A client device specific rule must not exist!"); link=$Link });
:set ($Seen->$Ssid) 1;
:if ($NewPsk != $OldPsk) do={
$LogPrint info $ScriptName ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")");
/caps-man/access-list/set $AccList private-passphrase=$NewPsk;
:if ([ :len [ /caps-man/actual-interface-configuration/find where configuration.ssid=$Ssid !disabled ] ] > 0) do={
:if ($Seen->$Ssid = 1) do={
$LogPrint debug $ScriptName ("Already sent a mail for SSID " . $Ssid . ", skipping.");
} else={
:local Link ($DailyPskQrCodeUrl . \
"?scale=8&level=1&ssid=" . [ $UrlEncode $Ssid ] . "&pass=" . [ $UrlEncode $NewPsk ]);
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "calendar" ] . "daily PSK " . $Ssid); \
message=("This is the daily PSK on " . $Identity . ":\n\n" . \
[ $FormatLine "SSID" $Ssid ] . "\n" . \
[ $FormatLine "PSK" $NewPsk ] . "\n" . \
[ $FormatLine "Date" $Date ] . "\n\n" . \
"A client device specific rule must not exist!"); link=$Link });
:set ($Seen->$Ssid) 1;
}
}
}
}
}
} on-error={ }

View file

@ -11,76 +11,81 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global DailyPskMatchComment;
:global DailyPskQrCodeUrl;
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global FormatLine;
:global LogPrintExit2;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global UrlEncode;
:global WaitForFile;
:global WaitFullyConnected;
:global DailyPskMatchComment;
:global DailyPskQrCodeUrl;
:global Identity;
$ScriptLock $0;
$WaitFullyConnected;
:global FormatLine;
:global LogPrint;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global UrlEncode;
:global WaitForFile;
:global WaitFullyConnected;
# return pseudo-random string for PSK
:local GeneratePSK do={
:local Date [ :tostr $1 ];
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
$WaitFullyConnected;
:global DailyPskSecrets;
# return pseudo-random string for PSK
:local GeneratePSK do={
:local Date [ :tostr $1 ];
:global ParseDate;
:global DailyPskSecrets;
:set Date [ $ParseDate $Date ];
:global ParseDate;
:local A ((14 - ($Date->"month")) / 12);
:local B (($Date->"year") - $A);
:local C (($Date->"month") + 12 * $A - 2);
:local WeekDay (7000 + ($Date->"day") + $B + ($B / 4) - ($B / 100) + ($B / 400) + ((31 * $C) / 12));
:set WeekDay ($WeekDay - (($WeekDay / 7) * 7));
:set Date [ $ParseDate $Date ];
:return (($DailyPskSecrets->0->(($Date->"day") - 1)) . \
($DailyPskSecrets->1->(($Date->"month") - 1)) . \
($DailyPskSecrets->2->$WeekDay));
}
:local A ((14 - ($Date->"month")) / 12);
:local B (($Date->"year") - $A);
:local C (($Date->"month") + 12 * $A - 2);
:local WeekDay (7000 + ($Date->"day") + $B + ($B / 4) - ($B / 100) + ($B / 400) + ((31 * $C) / 12));
:set WeekDay ($WeekDay - (($WeekDay / 7) * 7));
:local Seen ({});
:local Date [ /system/clock/get date ];
:local NewPsk [ $GeneratePSK $Date ];
:return (($DailyPskSecrets->0->(($Date->"day") - 1)) . \
($DailyPskSecrets->1->(($Date->"month") - 1)) . \
($DailyPskSecrets->2->$WeekDay));
}
:foreach AccList in=[ /interface/wireless/access-list/find where comment~$DailyPskMatchComment ] do={
:local IntName [ /interface/wireless/access-list/get $AccList interface ];
:local Ssid [ /interface/wireless/get $IntName ssid ];
:local OldPsk [ /interface/wireless/access-list/get $AccList private-pre-shared-key ];
:local Skip 0;
:local Seen ({});
:local Date [ /system/clock/get date ];
:local NewPsk [ $GeneratePSK $Date ];
:if ($NewPsk != $OldPsk) do={
$LogPrintExit2 info $0 ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")") false;
/interface/wireless/access-list/set $AccList private-pre-shared-key=$NewPsk;
:foreach AccList in=[ /interface/wireless/access-list/find where comment~$DailyPskMatchComment ] do={
:local IntName [ /interface/wireless/access-list/get $AccList interface ];
:local Ssid [ /interface/wireless/get $IntName ssid ];
:local OldPsk [ /interface/wireless/access-list/get $AccList private-pre-shared-key ];
:local Skip 0;
:if ([ :len [ /interface/wireless/find where name=$IntName !disabled ] ] = 1) do={
:if ($Seen->$Ssid = 1) do={
$LogPrintExit2 debug $0 ("Already sent a mail for SSID " . $Ssid . ", skipping.") false;
} else={
:local Link ($DailyPskQrCodeUrl . \
"?scale=8&level=1&ssid=" . [ $UrlEncode $Ssid ] . "&pass=" . [ $UrlEncode $NewPsk ]);
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "calendar" ] . "daily PSK " . $Ssid); \
message=("This is the daily PSK on " . $Identity . ":\n\n" . \
[ $FormatLine "SSID" $Ssid ] . "\n" . \
[ $FormatLine "PSK" $NewPsk ] . "\n" . \
[ $FormatLine "Date" $Date ] . "\n\n" . \
"A client device specific rule must not exist!"); link=$Link });
:set ($Seen->$Ssid) 1;
:if ($NewPsk != $OldPsk) do={
$LogPrint info $ScriptName ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")");
/interface/wireless/access-list/set $AccList private-pre-shared-key=$NewPsk;
:if ([ :len [ /interface/wireless/find where name=$IntName !disabled ] ] = 1) do={
:if ($Seen->$Ssid = 1) do={
$LogPrint debug $ScriptName ("Already sent a mail for SSID " . $Ssid . ", skipping.");
} else={
:local Link ($DailyPskQrCodeUrl . \
"?scale=8&level=1&ssid=" . [ $UrlEncode $Ssid ] . "&pass=" . [ $UrlEncode $NewPsk ]);
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "calendar" ] . "daily PSK " . $Ssid); \
message=("This is the daily PSK on " . $Identity . ":\n\n" . \
[ $FormatLine "SSID" $Ssid ] . "\n" . \
[ $FormatLine "PSK" $NewPsk ] . "\n" . \
[ $FormatLine "Date" $Date ] . "\n\n" . \
"A client device specific rule must not exist!"); link=$Link });
:set ($Seen->$Ssid) 1;
}
}
}
}
}
} on-error={ }

View file

@ -12,98 +12,96 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global DailyPskMatchComment;
:global DailyPskQrCodeUrl;
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global FormatLine;
:global LogPrintExit2;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global UrlEncode;
:global WaitForFile;
:global WaitFullyConnected;
:global DailyPskMatchComment;
:global DailyPskQrCodeUrl;
:global Identity;
$ScriptLock $0;
$WaitFullyConnected;
:global FormatLine;
:global LogPrint;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global UrlEncode;
:global WaitForFile;
:global WaitFullyConnected;
# return pseudo-random string for PSK
:local GeneratePSK do={
:local Date [ :tostr $1 ];
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
$WaitFullyConnected;
:global DailyPskSecrets;
# return pseudo-random string for PSK
:local GeneratePSK do={
:local Date [ :tostr $1 ];
:global ParseDate;
:global DailyPskSecrets;
:set Date [ $ParseDate $Date ];
:global ParseDate;
:local A ((14 - ($Date->"month")) / 12);
:local B (($Date->"year") - $A);
:local C (($Date->"month") + 12 * $A - 2);
:local WeekDay (7000 + ($Date->"day") + $B + ($B / 4) - ($B / 100) + ($B / 400) + ((31 * $C) / 12));
:set WeekDay ($WeekDay - (($WeekDay / 7) * 7));
:set Date [ $ParseDate $Date ];
:return (($DailyPskSecrets->0->(($Date->"day") - 1)) . \
($DailyPskSecrets->1->(($Date->"month") - 1)) . \
($DailyPskSecrets->2->$WeekDay));
}
:local A ((14 - ($Date->"month")) / 12);
:local B (($Date->"year") - $A);
:local C (($Date->"month") + 12 * $A - 2);
:local WeekDay (7000 + ($Date->"day") + $B + ($B / 4) - ($B / 100) + ($B / 400) + ((31 * $C) / 12));
:set WeekDay ($WeekDay - (($WeekDay / 7) * 7));
:local Seen ({});
:local Date [ /system/clock/get date ];
:local NewPsk [ $GeneratePSK $Date ];
:return (($DailyPskSecrets->0->(($Date->"day") - 1)) . \
($DailyPskSecrets->1->(($Date->"month") - 1)) . \
($DailyPskSecrets->2->$WeekDay));
}
:foreach AccList in=[ /caps-man/access-list/find where comment~$DailyPskMatchComment ] do={
:foreach AccList in=[ /interface/wifi/access-list/find where comment~$DailyPskMatchComment ] do={
:foreach AccList in=[ /interface/wifiwave2/access-list/find where comment~$DailyPskMatchComment ] do={
:foreach AccList in=[ /interface/wireless/access-list/find where comment~$DailyPskMatchComment ] do={
:local SsidRegExp [ /caps-man/access-list/get $AccList ssid-regexp ];
:local SsidRegExp [ /interface/wifi/access-list/get $AccList ssid-regexp ];
:local SsidRegExp [ /interface/wifiwave2/access-list/get $AccList ssid-regexp ];
:local Configuration ([ /caps-man/configuration/find where ssid~$SsidRegExp ]->0);
:local Configuration ([ /interface/wifi/configuration/find where ssid~$SsidRegExp ]->0);
:local Configuration ([ /interface/wifiwave2/configuration/find where ssid~$SsidRegExp ]->0);
:local Ssid [ /caps-man/configuration/get $Configuration ssid ];
:local Ssid [ /interface/wifi/configuration/get $Configuration ssid ];
:local Ssid [ /interface/wifiwave2/configuration/get $Configuration ssid ];
:local OldPsk [ /caps-man/access-list/get $AccList private-passphrase ];
:local OldPsk [ /interface/wifi/access-list/get $AccList passphrase ];
:local OldPsk [ /interface/wifiwave2/access-list/get $AccList passphrase ];
# /caps-man/ /interface/wifi/ /interface/wifiwave2/ above - /interface/wireless/ below
:local IntName [ /interface/wireless/access-list/get $AccList interface ];
:local Ssid [ /interface/wireless/get $IntName ssid ];
:local OldPsk [ /interface/wireless/access-list/get $AccList private-pre-shared-key ];
:local Skip 0;
:local Seen ({});
:local Date [ /system/clock/get date ];
:local NewPsk [ $GeneratePSK $Date ];
:if ($NewPsk != $OldPsk) do={
$LogPrintExit2 info $0 ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")") false;
/caps-man/access-list/set $AccList private-passphrase=$NewPsk;
/interface/wifi/access-list/set $AccList passphrase=$NewPsk;
/interface/wifiwave2/access-list/set $AccList passphrase=$NewPsk;
/interface/wireless/access-list/set $AccList private-pre-shared-key=$NewPsk;
:foreach AccList in=[ /caps-man/access-list/find where comment~$DailyPskMatchComment ] do={
:foreach AccList in=[ /interface/wifi/access-list/find where comment~$DailyPskMatchComment ] do={
:foreach AccList in=[ /interface/wireless/access-list/find where comment~$DailyPskMatchComment ] do={
:local SsidRegExp [ /caps-man/access-list/get $AccList ssid-regexp ];
:local SsidRegExp [ /interface/wifi/access-list/get $AccList ssid-regexp ];
:local Configuration ([ /caps-man/configuration/find where ssid~$SsidRegExp ]->0);
:local Configuration ([ /interface/wifi/configuration/find where ssid~$SsidRegExp ]->0);
:local Ssid [ /caps-man/configuration/get $Configuration ssid ];
:local Ssid [ /interface/wifi/configuration/get $Configuration ssid ];
:local OldPsk [ /caps-man/access-list/get $AccList private-passphrase ];
:local OldPsk [ /interface/wifi/access-list/get $AccList passphrase ];
# /caps-man/ /interface/wifi/ above - /interface/wireless/ below
:local IntName [ /interface/wireless/access-list/get $AccList interface ];
:local Ssid [ /interface/wireless/get $IntName ssid ];
:local OldPsk [ /interface/wireless/access-list/get $AccList private-pre-shared-key ];
:local Skip 0;
:if ([ :len [ /caps-man/actual-interface-configuration/find where configuration.ssid=$Ssid !disabled ] ] > 0) do={
:if ([ :len [ /interface/wifi/actual-configuration/find where configuration.ssid=$Ssid ] ] > 0) do={
:if ([ :len [ /interface/wifiwave2/actual-configuration/find where configuration.ssid=$Ssid ] ] > 0) do={
:if ([ :len [ /interface/wireless/find where name=$IntName !disabled ] ] = 1) do={
:if ($Seen->$Ssid = 1) do={
$LogPrintExit2 debug $0 ("Already sent a mail for SSID " . $Ssid . ", skipping.") false;
} else={
:local Link ($DailyPskQrCodeUrl . \
"?scale=8&level=1&ssid=" . [ $UrlEncode $Ssid ] . "&pass=" . [ $UrlEncode $NewPsk ]);
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "calendar" ] . "daily PSK " . $Ssid); \
message=("This is the daily PSK on " . $Identity . ":\n\n" . \
[ $FormatLine "SSID" $Ssid ] . "\n" . \
[ $FormatLine "PSK" $NewPsk ] . "\n" . \
[ $FormatLine "Date" $Date ] . "\n\n" . \
"A client device specific rule must not exist!"); link=$Link });
:set ($Seen->$Ssid) 1;
:if ($NewPsk != $OldPsk) do={
$LogPrint info $ScriptName ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")");
/caps-man/access-list/set $AccList private-passphrase=$NewPsk;
/interface/wifi/access-list/set $AccList passphrase=$NewPsk;
/interface/wireless/access-list/set $AccList private-pre-shared-key=$NewPsk;
:if ([ :len [ /caps-man/actual-interface-configuration/find where configuration.ssid=$Ssid !disabled ] ] > 0) do={
:if ([ :len [ /interface/wifi/actual-configuration/find where configuration.ssid=$Ssid ] ] > 0) do={
:if ([ :len [ /interface/wireless/find where name=$IntName !disabled ] ] = 1) do={
:if ($Seen->$Ssid = 1) do={
$LogPrint debug $ScriptName ("Already sent a mail for SSID " . $Ssid . ", skipping.");
} else={
:local Link ($DailyPskQrCodeUrl . \
"?scale=8&level=1&ssid=" . [ $UrlEncode $Ssid ] . "&pass=" . [ $UrlEncode $NewPsk ]);
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "calendar" ] . "daily PSK " . $Ssid); \
message=("This is the daily PSK on " . $Identity . ":\n\n" . \
[ $FormatLine "SSID" $Ssid ] . "\n" . \
[ $FormatLine "PSK" $NewPsk ] . "\n" . \
[ $FormatLine "Date" $Date ] . "\n\n" . \
"A client device specific rule must not exist!"); link=$Link });
:set ($Seen->$Ssid) 1;
}
}
}
}
}
} on-error={ }

View file

@ -11,77 +11,82 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global DailyPskMatchComment;
:global DailyPskQrCodeUrl;
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global FormatLine;
:global LogPrintExit2;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global UrlEncode;
:global WaitForFile;
:global WaitFullyConnected;
:global DailyPskMatchComment;
:global DailyPskQrCodeUrl;
:global Identity;
$ScriptLock $0;
$WaitFullyConnected;
:global FormatLine;
:global LogPrint;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global UrlEncode;
:global WaitForFile;
:global WaitFullyConnected;
# return pseudo-random string for PSK
:local GeneratePSK do={
:local Date [ :tostr $1 ];
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
$WaitFullyConnected;
:global DailyPskSecrets;
# return pseudo-random string for PSK
:local GeneratePSK do={
:local Date [ :tostr $1 ];
:global ParseDate;
:global DailyPskSecrets;
:set Date [ $ParseDate $Date ];
:global ParseDate;
:local A ((14 - ($Date->"month")) / 12);
:local B (($Date->"year") - $A);
:local C (($Date->"month") + 12 * $A - 2);
:local WeekDay (7000 + ($Date->"day") + $B + ($B / 4) - ($B / 100) + ($B / 400) + ((31 * $C) / 12));
:set WeekDay ($WeekDay - (($WeekDay / 7) * 7));
:set Date [ $ParseDate $Date ];
:return (($DailyPskSecrets->0->(($Date->"day") - 1)) . \
($DailyPskSecrets->1->(($Date->"month") - 1)) . \
($DailyPskSecrets->2->$WeekDay));
}
:local A ((14 - ($Date->"month")) / 12);
:local B (($Date->"year") - $A);
:local C (($Date->"month") + 12 * $A - 2);
:local WeekDay (7000 + ($Date->"day") + $B + ($B / 4) - ($B / 100) + ($B / 400) + ((31 * $C) / 12));
:set WeekDay ($WeekDay - (($WeekDay / 7) * 7));
:local Seen ({});
:local Date [ /system/clock/get date ];
:local NewPsk [ $GeneratePSK $Date ];
:return (($DailyPskSecrets->0->(($Date->"day") - 1)) . \
($DailyPskSecrets->1->(($Date->"month") - 1)) . \
($DailyPskSecrets->2->$WeekDay));
}
:foreach AccList in=[ /interface/wifi/access-list/find where comment~$DailyPskMatchComment ] do={
:local SsidRegExp [ /interface/wifi/access-list/get $AccList ssid-regexp ];
:local Configuration ([ /interface/wifi/configuration/find where ssid~$SsidRegExp ]->0);
:local Ssid [ /interface/wifi/configuration/get $Configuration ssid ];
:local OldPsk [ /interface/wifi/access-list/get $AccList passphrase ];
:local Skip 0;
:local Seen ({});
:local Date [ /system/clock/get date ];
:local NewPsk [ $GeneratePSK $Date ];
:if ($NewPsk != $OldPsk) do={
$LogPrintExit2 info $0 ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")") false;
/interface/wifi/access-list/set $AccList passphrase=$NewPsk;
:foreach AccList in=[ /interface/wifi/access-list/find where comment~$DailyPskMatchComment ] do={
:local SsidRegExp [ /interface/wifi/access-list/get $AccList ssid-regexp ];
:local Configuration ([ /interface/wifi/configuration/find where ssid~$SsidRegExp ]->0);
:local Ssid [ /interface/wifi/configuration/get $Configuration ssid ];
:local OldPsk [ /interface/wifi/access-list/get $AccList passphrase ];
:local Skip 0;
:if ([ :len [ /interface/wifi/actual-configuration/find where configuration.ssid=$Ssid ] ] > 0) do={
:if ($Seen->$Ssid = 1) do={
$LogPrintExit2 debug $0 ("Already sent a mail for SSID " . $Ssid . ", skipping.") false;
} else={
:local Link ($DailyPskQrCodeUrl . \
"?scale=8&level=1&ssid=" . [ $UrlEncode $Ssid ] . "&pass=" . [ $UrlEncode $NewPsk ]);
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "calendar" ] . "daily PSK " . $Ssid); \
message=("This is the daily PSK on " . $Identity . ":\n\n" . \
[ $FormatLine "SSID" $Ssid ] . "\n" . \
[ $FormatLine "PSK" $NewPsk ] . "\n" . \
[ $FormatLine "Date" $Date ] . "\n\n" . \
"A client device specific rule must not exist!"); link=$Link });
:set ($Seen->$Ssid) 1;
:if ($NewPsk != $OldPsk) do={
$LogPrint info $ScriptName ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")");
/interface/wifi/access-list/set $AccList passphrase=$NewPsk;
:if ([ :len [ /interface/wifi/actual-configuration/find where configuration.ssid=$Ssid ] ] > 0) do={
:if ($Seen->$Ssid = 1) do={
$LogPrint debug $ScriptName ("Already sent a mail for SSID " . $Ssid . ", skipping.");
} else={
:local Link ($DailyPskQrCodeUrl . \
"?scale=8&level=1&ssid=" . [ $UrlEncode $Ssid ] . "&pass=" . [ $UrlEncode $NewPsk ]);
$SendNotification2 ({ origin=$ScriptName; \
subject=([ $SymbolForNotification "calendar" ] . "daily PSK " . $Ssid); \
message=("This is the daily PSK on " . $Identity . ":\n\n" . \
[ $FormatLine "SSID" $Ssid ] . "\n" . \
[ $FormatLine "PSK" $NewPsk ] . "\n" . \
[ $FormatLine "Date" $Date ] . "\n\n" . \
"A client device specific rule must not exist!"); link=$Link });
:set ($Seen->$Ssid) 1;
}
}
}
}
}
} on-error={ }

View file

@ -1,87 +0,0 @@
#!rsc by RouterOS
# RouterOS script: daily-psk.wifiwave2
# Copyright (c) 2013-2024 Christian Hesse <mail@eworm.de>
# Michael Gisbers <michael@gisbers.de>
# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md
#
# requires RouterOS, version=7.12
#
# update daily PSK (pre shared key)
# https://git.eworm.de/cgit/routeros-scripts/about/doc/daily-psk.md
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global DailyPskMatchComment;
:global DailyPskQrCodeUrl;
:global Identity;
:global FormatLine;
:global LogPrintExit2;
:global ScriptLock;
:global SendNotification2;
:global SymbolForNotification;
:global UrlEncode;
:global WaitForFile;
:global WaitFullyConnected;
$ScriptLock $0;
$WaitFullyConnected;
# return pseudo-random string for PSK
:local GeneratePSK do={
:local Date [ :tostr $1 ];
:global DailyPskSecrets;
:global ParseDate;
:set Date [ $ParseDate $Date ];
:local A ((14 - ($Date->"month")) / 12);
:local B (($Date->"year") - $A);
:local C (($Date->"month") + 12 * $A - 2);
:local WeekDay (7000 + ($Date->"day") + $B + ($B / 4) - ($B / 100) + ($B / 400) + ((31 * $C) / 12));
:set WeekDay ($WeekDay - (($WeekDay / 7) * 7));
:return (($DailyPskSecrets->0->(($Date->"day") - 1)) . \
($DailyPskSecrets->1->(($Date->"month") - 1)) . \
($DailyPskSecrets->2->$WeekDay));
}
:local Seen ({});
:local Date [ /system/clock/get date ];
:local NewPsk [ $GeneratePSK $Date ];
:foreach AccList in=[ /interface/wifiwave2/access-list/find where comment~$DailyPskMatchComment ] do={
:local SsidRegExp [ /interface/wifiwave2/access-list/get $AccList ssid-regexp ];
:local Configuration ([ /interface/wifiwave2/configuration/find where ssid~$SsidRegExp ]->0);
:local Ssid [ /interface/wifiwave2/configuration/get $Configuration ssid ];
:local OldPsk [ /interface/wifiwave2/access-list/get $AccList passphrase ];
:local Skip 0;
:if ($NewPsk != $OldPsk) do={
$LogPrintExit2 info $0 ("Updating daily PSK for " . $Ssid . " to " . $NewPsk . " (was " . $OldPsk . ")") false;
/interface/wifiwave2/access-list/set $AccList passphrase=$NewPsk;
:if ([ :len [ /interface/wifiwave2/actual-configuration/find where configuration.ssid=$Ssid ] ] > 0) do={
:if ($Seen->$Ssid = 1) do={
$LogPrintExit2 debug $0 ("Already sent a mail for SSID " . $Ssid . ", skipping.") false;
} else={
:local Link ($DailyPskQrCodeUrl . \
"?scale=8&level=1&ssid=" . [ $UrlEncode $Ssid ] . "&pass=" . [ $UrlEncode $NewPsk ]);
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "calendar" ] . "daily PSK " . $Ssid); \
message=("This is the daily PSK on " . $Identity . ":\n\n" . \
[ $FormatLine "SSID" $Ssid ] . "\n" . \
[ $FormatLine "PSK" $NewPsk ] . "\n" . \
[ $FormatLine "Date" $Date ] . "\n\n" . \
"A client device specific rule must not exist!"); link=$Link });
:set ($Seen->$Ssid) 1;
}
}
}
}

View file

@ -11,24 +11,29 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global LogPrintExit2;
:global ScriptLock;
:do {
:local ScriptName [ :jobname ];
$ScriptLock $0;
:global LogPrint;
:global ScriptLock;
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
:local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:local NewComment;
:local AccessList ([ /caps-man/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
:set NewComment [ /caps-man/access-list/get $AccessList comment ];
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
:if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={
$LogPrintExit2 info $0 ("Updating comment for DHCP lease " . $LeaseVal->"active-mac-address" . ": " . $NewComment) false;
/ip/dhcp-server/lease/set comment=$NewComment $Lease;
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
:local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:local NewComment;
:local AccessList ([ /caps-man/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
:set NewComment [ /caps-man/access-list/get $AccessList comment ];
}
:if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={
$LogPrint info $ScriptName ("Updating comment for DHCP lease " . $LeaseVal->"active-mac-address" . ": " . $NewComment);
/ip/dhcp-server/lease/set comment=$NewComment $Lease;
}
}
}
} on-error={ }

View file

@ -11,24 +11,29 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global LogPrintExit2;
:global ScriptLock;
:do {
:local ScriptName [ :jobname ];
$ScriptLock $0;
:global LogPrint;
:global ScriptLock;
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
:local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:local NewComment;
:local AccessList ([ /interface/wireless/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
:set NewComment [ /interface/wireless/access-list/get $AccessList comment ];
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
:if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={
$LogPrintExit2 info $0 ("Updating comment for DHCP lease " . $LeaseVal->"active-mac-address" . ": " . $NewComment) false;
/ip/dhcp-server/lease/set comment=$NewComment $Lease;
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
:local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:local NewComment;
:local AccessList ([ /interface/wireless/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
:set NewComment [ /interface/wireless/access-list/get $AccessList comment ];
}
:if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={
$LogPrint info $ScriptName ("Updating comment for DHCP lease " . $LeaseVal->"active-mac-address" . ": " . $NewComment);
/ip/dhcp-server/lease/set comment=$NewComment $Lease;
}
}
}
} on-error={ }

View file

@ -12,30 +12,33 @@
# !! This is just a template to generate the real script!
# !! Pattern '%TEMPL%' is replaced, paths are filtered.
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global LogPrintExit2;
:global ScriptLock;
:do {
:local ScriptName [ :jobname ];
$ScriptLock $0;
:global LogPrint;
:global ScriptLock;
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
:local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:local NewComment;
:local AccessList ([ /caps-man/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:local AccessList ([ /interface/wifi/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:local AccessList ([ /interface/wifiwave2/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:local AccessList ([ /interface/wireless/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
:set NewComment [ /caps-man/access-list/get $AccessList comment ];
:set NewComment [ /interface/wifi/access-list/get $AccessList comment ];
:set NewComment [ /interface/wifiwave2/access-list/get $AccessList comment ];
:set NewComment [ /interface/wireless/access-list/get $AccessList comment ];
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
:if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={
$LogPrintExit2 info $0 ("Updating comment for DHCP lease " . $LeaseVal->"active-mac-address" . ": " . $NewComment) false;
/ip/dhcp-server/lease/set comment=$NewComment $Lease;
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
:local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:local NewComment;
:local AccessList ([ /caps-man/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:local AccessList ([ /interface/wifi/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:local AccessList ([ /interface/wireless/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
:set NewComment [ /caps-man/access-list/get $AccessList comment ];
:set NewComment [ /interface/wifi/access-list/get $AccessList comment ];
:set NewComment [ /interface/wireless/access-list/get $AccessList comment ];
}
:if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={
$LogPrint info $ScriptName ("Updating comment for DHCP lease " . $LeaseVal->"active-mac-address" . ": " . $NewComment);
/ip/dhcp-server/lease/set comment=$NewComment $Lease;
}
}
}
} on-error={ }

View file

@ -11,24 +11,29 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global LogPrintExit2;
:global ScriptLock;
:do {
:local ScriptName [ :jobname ];
$ScriptLock $0;
:global LogPrint;
:global ScriptLock;
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
:local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:local NewComment;
:local AccessList ([ /interface/wifi/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
:set NewComment [ /interface/wifi/access-list/get $AccessList comment ];
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
:if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={
$LogPrintExit2 info $0 ("Updating comment for DHCP lease " . $LeaseVal->"active-mac-address" . ": " . $NewComment) false;
/ip/dhcp-server/lease/set comment=$NewComment $Lease;
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
:local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:local NewComment;
:local AccessList ([ /interface/wifi/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
:set NewComment [ /interface/wifi/access-list/get $AccessList comment ];
}
:if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={
$LogPrint info $ScriptName ("Updating comment for DHCP lease " . $LeaseVal->"active-mac-address" . ": " . $NewComment);
/ip/dhcp-server/lease/set comment=$NewComment $Lease;
}
}
}
} on-error={ }

View file

@ -1,34 +0,0 @@
#!rsc by RouterOS
# RouterOS script: dhcp-lease-comment.wifiwave2
# Copyright (c) 2013-2024 Christian Hesse <mail@eworm.de>
# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md
#
# provides: lease-script, order=60
# requires RouterOS, version=7.12
#
# update dhcp-server lease comment with infos from access-list
# https://git.eworm.de/cgit/routeros-scripts/about/doc/dhcp-lease-comment.md
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global LogPrintExit2;
:global ScriptLock;
$ScriptLock $0;
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic=yes status=bound ] do={
:local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:local NewComment;
:local AccessList ([ /interface/wifiwave2/access-list/find where mac-address=($LeaseVal->"active-mac-address") ]->0);
:if ([ :len $AccessList ] > 0) do={
:set NewComment [ /interface/wifiwave2/access-list/get $AccessList comment ];
}
:if ([ :len $NewComment ] != 0 && $LeaseVal->"comment" != $NewComment) do={
$LogPrintExit2 info $0 ("Updating comment for DHCP lease " . $LeaseVal->"active-mac-address" . ": " . $NewComment) false;
/ip/dhcp-server/lease/set comment=$NewComment $Lease;
}
}

View file

@ -9,113 +9,118 @@
# check DHCP leases and add/remove/update DNS entries
# https://git.eworm.de/cgit/routeros-scripts/about/doc/dhcp-to-dns.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global Domain;
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global CleanName;
:global EitherOr;
:global IfThenElse;
:global LogPrintExit2;
:global LogPrintOnce;
:global ParseKeyValueStore;
:global ScriptLock;
:global Domain;
:global Identity;
$ScriptLock $0 false 10;
:global CleanName;
:global EitherOr;
:global IfThenElse;
:global LogPrint;
:global LogPrintOnce;
:global ParseKeyValueStore;
:global ScriptLock;
:local Ttl 5m;
:local CommentPrefix ("managed by " . $0);
:local CommentString ("--- " . $0 . " above ---");
:if ([ :len [ /ip/dns/static/find where (name=$CommentString or (comment=$CommentString and name=-)) type=NXDOMAIN disabled ] ] = 0) do={
/ip/dns/static/add name=$CommentString type=NXDOMAIN disabled=yes;
$LogPrintExit2 warning $0 ("Added disabled static dns record with name '" . $CommentString . "'.") false;
}
:local PlaceBefore ([ /ip/dns/static/find where (name=$CommentString or (comment=$CommentString and name=-)) type=NXDOMAIN disabled ]->0);
:foreach DnsRecord in=[ /ip/dns/static/find where comment~("^" . $CommentPrefix . "\\b") (!type or type=A) ] do={
:local DnsRecordVal [ /ip/dns/static/get $DnsRecord ];
:local DnsRecordInfo [ $ParseKeyValueStore ($DnsRecordVal->"comment") ];
:local MacInServer ($DnsRecordInfo->"macaddress" . " in " . $DnsRecordInfo->"server");
:if ([ :len [ /ip/dhcp-server/lease/find where active-mac-address=($DnsRecordInfo->"macaddress") \
active-address=($DnsRecordVal->"address") server=($DnsRecordInfo->"server") status=bound ] ] > 0) do={
$LogPrintExit2 debug $0 ("Lease for " . $MacInServer . " (" . $DnsRecordVal->"name" . ") still exists. Not deleting record.") false;
} else={
:local Found false;
$LogPrintExit2 info $0 ("Lease expired for " . $MacInServer . ", deleting record (" . $DnsRecordVal->"name" . ").") false;
/ip/dns/static/remove $DnsRecord;
/ip/dns/static/remove [ find where type=CNAME comment=($DnsRecordVal->"comment") ];
}
}
:foreach Lease in=[ /ip/dhcp-server/lease/find where status=bound ] do={
:local LeaseVal;
:do {
:set LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:if ([ :len [ /ip/dhcp-server/lease/find where active-mac-address=($LeaseVal->"active-mac-address") status=bound ] ] > 1) do={
$LogPrintOnce info $0 ("Multiple bound leases found for mac-address " . ($LeaseVal->"active-mac-address") . "!") false;
}
} on-error={
$LogPrintExit2 debug $0 ("A lease just vanished, ignoring.") false;
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:error false;
}
:if ([ :len ($LeaseVal->"active-address") ] > 0) do={
:local Comment ($CommentPrefix . ", macaddress=" . $LeaseVal->"active-mac-address" . ", server=" . $LeaseVal->"server");
:local MacDash [ $CleanName ($LeaseVal->"active-mac-address") ];
:local HostName [ $CleanName [ $EitherOr ([ $ParseKeyValueStore ($LeaseVal->"comment") ]->"hostname") ($LeaseVal->"host-name") ] ];
:local Network [ /ip/dhcp-server/network/find where ($LeaseVal->"active-address") in address ];
:local NetworkVal;
:if ([ :len $Network ] > 0) do={
:set NetworkVal [ /ip/dhcp-server/network/get ($Network->0) ];
:local Ttl 5m;
:local CommentPrefix ("managed by " . $ScriptName);
:local CommentString ("--- " . $ScriptName . " above ---");
:if ([ :len [ /ip/dns/static/find where (name=$CommentString or (comment=$CommentString and name=-)) type=NXDOMAIN disabled ] ] = 0) do={
/ip/dns/static/add name=$CommentString type=NXDOMAIN disabled=yes;
$LogPrint warning $ScriptName ("Added disabled static dns record with name '" . $CommentString . "'.");
}
:local PlaceBefore ([ /ip/dns/static/find where (name=$CommentString or (comment=$CommentString and name=-)) type=NXDOMAIN disabled ]->0);
:foreach DnsRecord in=[ /ip/dns/static/find where comment~("^" . $CommentPrefix . "\\b") (!type or type=A) ] do={
:local DnsRecordVal [ /ip/dns/static/get $DnsRecord ];
:local DnsRecordInfo [ $ParseKeyValueStore ($DnsRecordVal->"comment") ];
:local MacInServer ($DnsRecordInfo->"macaddress" . " in " . $DnsRecordInfo->"server");
:if ([ :len [ /ip/dhcp-server/lease/find where active-mac-address=($DnsRecordInfo->"macaddress") \
active-address=($DnsRecordVal->"address") server=($DnsRecordInfo->"server") status=bound ] ] > 0) do={
$LogPrint debug $ScriptName ("Lease for " . $MacInServer . " (" . $DnsRecordVal->"name" . ") still exists. Not deleting record.");
} else={
:local Found false;
$LogPrint info $ScriptName ("Lease expired for " . $MacInServer . ", deleting record (" . $DnsRecordVal->"name" . ").");
/ip/dns/static/remove $DnsRecord;
/ip/dns/static/remove [ find where type=CNAME comment=($DnsRecordVal->"comment") ];
}
:local NetworkInfo [ $ParseKeyValueStore ($NetworkVal->"comment") ];
:local NetDomain ([ $IfThenElse ([ :len ($NetworkInfo->"name-extra") ] > 0) ($NetworkInfo->"name-extra" . ".") ] . \
[ $EitherOr [ $EitherOr ($NetworkInfo->"domain") ($NetworkVal->"domain") ] $Domain ]);
:local FullA ($MacDash . "." . $NetDomain);
:local FullCN ($HostName . "." . $NetDomain);
:local MacInServer ($LeaseVal->"active-mac-address" . " in " . $LeaseVal->"server");
}
:local DnsRecord [ /ip/dns/static/find where comment=$Comment (!type or type=A) ];
:if ([ :len $DnsRecord ] > 0) do={
:local DnsRecordVal [ /ip/dns/static/get $DnsRecord ];
:if ($DnsRecordVal->"address" = $LeaseVal->"active-address" && $DnsRecordVal->"name" = $FullA) do={
$LogPrintExit2 debug $0 ("The A record for " . $MacInServer . " (" . $FullA . ") does not need updating.") false;
} else={
$LogPrintExit2 info $0 ("Updating A record for " . $MacInServer . " (" . $FullA . " -> " . $LeaseVal->"active-address" . ").") false;
/ip/dns/static/set address=($LeaseVal->"active-address") name=$FullA $DnsRecord;
:foreach Lease in=[ /ip/dhcp-server/lease/find where status=bound ] do={
:local LeaseVal;
:do {
:set LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
:if ([ :len [ /ip/dhcp-server/lease/find where active-mac-address=($LeaseVal->"active-mac-address") status=bound ] ] > 1) do={
$LogPrintOnce info $ScriptName ("Multiple bound leases found for mac-address " . ($LeaseVal->"active-mac-address") . "!");
}
} on-error={
$LogPrint debug $ScriptName ("A lease just vanished, ignoring.");
}
:local CName [ /ip/dns/static/find where comment=$Comment type=CNAME ];
:if ([ :len $CName ] > 0) do={
:local CNameVal [ /ip/dns/static/get $CName ];
:if ($CNameVal->"name" != $FullCN || $CNameVal->"cname" != $FullA) do={
$LogPrintExit2 info $0 ("Deleting CNAME record with wrong data for " . $MacInServer . ".") false;
/ip/dns/static/remove $CName;
:if ([ :len ($LeaseVal->"active-address") ] > 0) do={
:local Comment ($CommentPrefix . ", macaddress=" . $LeaseVal->"active-mac-address" . ", server=" . $LeaseVal->"server");
:local MacDash [ $CleanName ($LeaseVal->"active-mac-address") ];
:local HostName [ $CleanName [ $EitherOr ([ $ParseKeyValueStore ($LeaseVal->"comment") ]->"hostname") ($LeaseVal->"host-name") ] ];
:local Network [ /ip/dhcp-server/network/find where ($LeaseVal->"active-address") in address ];
:local NetworkVal;
:if ([ :len $Network ] > 0) do={
:set NetworkVal [ /ip/dhcp-server/network/get ($Network->0) ];
}
:local NetworkInfo [ $ParseKeyValueStore ($NetworkVal->"comment") ];
:local NetDomain ([ $IfThenElse ([ :len ($NetworkInfo->"name-extra") ] > 0) ($NetworkInfo->"name-extra" . ".") ] . \
[ $EitherOr [ $EitherOr ($NetworkInfo->"domain") ($NetworkVal->"domain") ] $Domain ]);
:local FullA ($MacDash . "." . $NetDomain);
:local FullCN ($HostName . "." . $NetDomain);
:local MacInServer ($LeaseVal->"active-mac-address" . " in " . $LeaseVal->"server");
:local DnsRecord [ /ip/dns/static/find where comment=$Comment (!type or type=A) ];
:if ([ :len $DnsRecord ] > 0) do={
:local DnsRecordVal [ /ip/dns/static/get $DnsRecord ];
:if ($DnsRecordVal->"address" = $LeaseVal->"active-address" && $DnsRecordVal->"name" = $FullA) do={
$LogPrint debug $ScriptName ("The A record for " . $MacInServer . " (" . $FullA . ") does not need updating.");
} else={
$LogPrint info $ScriptName ("Updating A record for " . $MacInServer . " (" . $FullA . " -> " . $LeaseVal->"active-address" . ").");
/ip/dns/static/set address=($LeaseVal->"active-address") name=$FullA $DnsRecord;
}
:local CName [ /ip/dns/static/find where comment=$Comment type=CNAME ];
:if ([ :len $CName ] > 0) do={
:local CNameVal [ /ip/dns/static/get $CName ];
:if ($CNameVal->"name" != $FullCN || $CNameVal->"cname" != $FullA) do={
$LogPrint info $ScriptName ("Deleting CNAME record with wrong data for " . $MacInServer . ".");
/ip/dns/static/remove $CName;
}
}
:if ([ :len $HostName ] > 0 && [ :len [ /ip/dns/static/find where name=$FullCN type=CNAME ] ] = 0) do={
$LogPrint info $ScriptName ("Adding CNAME record for " . $MacInServer . " (" . $FullCN . " -> " . $FullA . ").");
/ip/dns/static/add name=$FullCN type=CNAME cname=$FullA ttl=$Ttl comment=$Comment place-before=$PlaceBefore;
}
} else={
$LogPrint info $ScriptName ("Adding A record for " . $MacInServer . " (" . $FullA . " -> " . $LeaseVal->"active-address" . ").");
/ip/dns/static/add name=$FullA type=A address=($LeaseVal->"active-address") ttl=$Ttl comment=$Comment place-before=$PlaceBefore;
:if ([ :len $HostName ] > 0 && [ :len [ /ip/dns/static/find where name=$FullCN type=CNAME ] ] = 0) do={
$LogPrint info $ScriptName ("Adding CNAME record for " . $MacInServer . " (" . $FullCN . " -> " . $FullA . ").");
/ip/dns/static/add name=$FullCN type=CNAME cname=$FullA ttl=$Ttl comment=$Comment place-before=$PlaceBefore;
}
}
:if ([ :len $HostName ] > 0 && [ :len [ /ip/dns/static/find where name=$FullCN type=CNAME ] ] = 0) do={
$LogPrintExit2 info $0 ("Adding CNAME record for " . $MacInServer . " (" . $FullCN . " -> " . $FullA . ").") false;
/ip/dns/static/add name=$FullCN type=CNAME cname=$FullA ttl=$Ttl comment=$Comment place-before=$PlaceBefore;
}
:if ([ :len [ /ip/dns/static/find where name=$FullA (!type or type=A) ] ] > 1) do={
$LogPrintOnce warning $ScriptName ("The name '" . $FullA . "' appeared in more than one A record!");
}
} else={
$LogPrintExit2 info $0 ("Adding A record for " . $MacInServer . " (" . $FullA . " -> " . $LeaseVal->"active-address" . ").") false;
/ip/dns/static/add name=$FullA type=A address=($LeaseVal->"active-address") ttl=$Ttl comment=$Comment place-before=$PlaceBefore;
:if ([ :len $HostName ] > 0 && [ :len [ /ip/dns/static/find where name=$FullCN type=CNAME ] ] = 0) do={
$LogPrintExit2 info $0 ("Adding CNAME record for " . $MacInServer . " (" . $FullCN . " -> " . $FullA . ").") false;
/ip/dns/static/add name=$FullCN type=CNAME cname=$FullA ttl=$Ttl comment=$Comment place-before=$PlaceBefore;
}
$LogPrint debug $ScriptName ("No address available... Ignoring.");
}
:if ([ :len [ /ip/dns/static/find where name=$FullA (!type or type=A) ] ] > 1) do={
$LogPrintOnce warning $0 ("The name '" . $FullA . "' appeared in more than one A record!") false;
}
} else={
$LogPrintExit2 debug $0 ("No address available... Ignoring.") false;
}
}
} on-error={ }

View file

@ -1,6 +1,13 @@
Find and remove access list duplicates
======================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base
@ -15,19 +22,14 @@ entries in wireless access list.
Requirements and installation
-----------------------------
Depending on whether you use `wifi` package (`/interface/wifi`), `wifiwave2`
package (`/interface/wifiwave2`), legacy wifi with CAPsMAN (`/caps-man`)
or local wireless interface (`/interface/wireless`) you need to install a
different script.
Depending on whether you use `wifi` package (`/interface/wifi`), legacy
wifi with CAPsMAN (`/caps-man`) or local wireless interface
(`/interface/wireless`) you need to install a different script.
For `wifi` (RouterOS 7.13 and later):
For `wifi`:
$ScriptInstallUpdate accesslist-duplicates.wifi;
For `wifiwave2` (up to RouterOS 7.12):
$ScriptInstallUpdate accesslist-duplicates.wifiwave2;
For legacy CAPsMAN:
$ScriptInstallUpdate accesslist-duplicates.capsman;

View file

@ -1,6 +1,13 @@
Upload backup to Mikrotik cloud
===============================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base
@ -12,10 +19,10 @@ Description
This script uploads
[binary backup to Mikrotik cloud](https://wiki.mikrotik.com/wiki/Manual:IP/Cloud#Backup).
> ⚠️ **Warning**: The used command can hit errors that a script can not handle.
> This may result in script termination (where no notification is sent) or
> malfunction of fetch command (where all up- and downloads break) for some
> time. Failed notifications are queued then.
> ⚠️ **Warning**: The used command can hit errors that a script can with
> workaround only. A notification *should* be sent anyway. But it can result
> in malfunction of fetch command (where all up- and downloads break) for
> some time. Failed notifications are queued then.
### Sample notification

View file

@ -1,6 +1,13 @@
Send backup via e-mail
======================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Save configuration to fallback partition
========================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Upload backup to server
=======================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Download packages for CAP upgrade from CAPsMAN
=============================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base
@ -23,31 +30,21 @@ as that is where packages are downloaded to and where the system expects
them.
Then just install the script on CAPsMAN device.
Depending on whether you use `wifi` package (`/interface/wifi`), `wifiwave2`
package (`/interface/wifiwave2`) or legacy wifi with CAPsMAN (`/caps-man`)
you need to install a different script.
Depending on whether you use `wifi` package (`/interface/wifi`) or legacy
wifi with CAPsMAN (`/caps-man`) you need to install a different script.
For `wifi` (RouterOS 7.13 and later):
For `wifi`:
$ScriptInstallUpdate capsman-download-packages.wifi;
For `wifiwave2` (up to RouterOS 7.12):
$ScriptInstallUpdate capsman-download-packages.wifiwave2;
For legacy CAPsMAN:
$ScriptInstallUpdate capsman-download-packages.capsman;
Optionally add a scheduler to run after startup. For `wifi` (RouterOS 7.13
and later):
Optionally add a scheduler to run after startup. For `wifi`:
/system/scheduler/add name=capsman-download-packages on-event="/system/script/run capsman-download-packages.wifi;" start-time=startup;
For `wifiwave2` (up to RouterOS 7.12):
/system/scheduler/add name=capsman-download-packages on-event="/system/script/run capsman-download-packages.wifiwave2;" start-time=startup;
For legacy CAPsMAN:
/system/scheduler/add name=capsman-download-packages on-event="/system/script/run capsman-download-packages.capsman;" start-time=startup;
@ -58,7 +55,6 @@ unconditionally.
If no packages are found the script downloads a default set of packages:
* `wifi`: `routeros` and `wifi-qcom` for *arm* and *arm64*, `wifi-qcom-ac` for *arm*
* `wifiwave2`: `routeros` and `wifiwave2` for *arm* and *arm64*
* legacy CAPsMAN: `routeros` and `wireless` for *arm* and *mipsbe*
> **Info**: If you have packages in the directory and things go wrong for

View file

@ -1,6 +1,13 @@
Run rolling CAP upgrades from CAPsMAN
=====================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base
@ -21,18 +28,13 @@ Requirements and installation
-----------------------------
Just install the script on CAPsMAN device.
Depending on whether you use `wifi` package (`/interface/wifi`), `wifiwave2`
package (`/interface/wifiwave2`) or legacy wifi with CAPsMAN (`/caps-man`)
you need to install a different script.
Depending on whether you use `wifi` package (`/interface/wifi`) or legacy
wifi with CAPsMAN (`/caps-man`) you need to install a different script.
For `wifi` (RouterOS 7.13 and later):
For `wifi`:
$ScriptInstallUpdate capsman-rolling-upgrade.wifi;
For `wifiwave2` (up to RouterOS 7.12):
$ScriptInstallUpdate capsman-rolling-upgrade.wifiwave2;
For legacy CAPsMAN:
$ScriptInstallUpdate capsman-rolling-upgrade.capsman;

View file

@ -1,6 +1,13 @@
Renew locally issued certificates
=================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Renew certificates and notify on expiration
===========================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Notify about health state
=========================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Notify on LTE firmware upgrade
==============================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Notify on RouterOS update
=========================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Collect MAC addresses in wireless access list
=============================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base
@ -22,19 +29,14 @@ and modify it to your needs.
Requirements and installation
-----------------------------
Depending on whether you use `wifi` package (`/interface/wifi`), `wifiwave2`
package (`/interface/wifiwave2`), legacy wifi with CAPsMAN (`/caps-man`)
or local wireless interface (`/interface/wireless`) you need to install a
different script.
Depending on whether you use `wifi` package (`/interface/wifi`), legacy
wifi with CAPsMAN (`/caps-man`) or local wireless interface
(`/interface/wireless`) you need to install a different script.
For `wifi` (RouterOS 7.13 and later):
For `wifi`:
$ScriptInstallUpdate collect-wireless-mac.wifi;
For `wifiwave2` (up to RouterOS 7.12):
$ScriptInstallUpdate collect-wireless-mac.wifiwave2;
For legacy CAPsMAN:
$ScriptInstallUpdate collect-wireless-mac.capsman;

View file

@ -1,6 +1,13 @@
Use wireless network with daily psk
===================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base
@ -21,23 +28,17 @@ Requirements and installation
Just install this script.
Depending on whether you use `wifi` package (`/interface/wifi`), `wifiwave2`
package (`/interface/wifiwave2`), legacy wifi with CAPsMAN (`/caps-man`)
or local wireless interface (`/interface/wireless`) you need to install a
different script and add schedulers to run the script:
Depending on whether you use `wifi` package (`/interface/wifi`), legacy
wifi with CAPsMAN (`/caps-man`) or local wireless interface
(`/interface/wireless`) you need to install a different script and add
schedulers to run the script:
For `wifi` (RouterOS 7.13 and later):
For `wifi`:
$ScriptInstallUpdate daily-psk.wifi;
/system/scheduler/add interval=1d name=daily-psk on-event="/system/script/run daily-psk.wifi;" start-time=03:00:00;
/system/scheduler/add name=daily-psk@startup on-event="/system/script/run daily-psk.wifi;" start-time=startup;
For `wifiwave2` (up to RouterOS 7.12):
$ScriptInstallUpdate daily-psk.wifiwave2;
/system/scheduler/add interval=1d name=daily-psk on-event="/system/script/run daily-psk.wifiwave2;" start-time=03:00:00;
/system/scheduler/add name=daily-psk@startup on-event="/system/script/run daily-psk.wifiwave2;" start-time=startup;
For legacy CAPsMAN:
$ScriptInstallUpdate daily-psk.capsman;
@ -64,14 +65,10 @@ The configuration goes to `global-config-overlay`, these are the parameters:
> [`global-config`](../global-config.rsc) (the one without `-overlay`) to
> your local `global-config-overlay` and modify it to your specific needs.
Then add an access list entry. For `wifi` (RouterOS 7.13 and later):
Then add an access list entry. For `wifi`:
/interface/wifi/access-list/add comment="Daily PSK" ssid-regexp="-guest\$" passphrase="ToBeChangedDaily";
For `wifiwave2` (up to RouterOS 7.12):
/interface/wifiwave2/access-list/add comment="Daily PSK" ssid-regexp="-guest\$" passphrase="ToBeChangedDaily";
For legacy CAPsMAN:
/caps-man/access-list/add comment="Daily PSK" ssid-regexp="-guest\$" private-passphrase="ToBeChangedDaily";

View file

@ -1,6 +1,13 @@
Comment DHCP leases with info from access list
==============================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base
@ -15,19 +22,14 @@ from wireless access list.
Requirements and installation
-----------------------------
Depending on whether you use `wifi` package (`/interface/wifi`), `wifiwave2`
package (`/interface/wifiwave2`), legacy wifi with CAPsMAN (`/caps-man`)
or local wireless interface (`/interface/wireless`) you need to install a
different script.
Depending on whether you use `wifi` package (`/interface/wifi`), legacy
wifi with CAPsMAN (`/caps-man`) or local wireless interface
(`/interface/wireless`) you need to install a different script.
For `wifi` (RouterOS 7.13 and later):
For `wifi`:
$ScriptInstallUpdate dhcp-lease-comment.wifi;
For `wifiwave2` (up to RouterOS 7.12):
$ScriptInstallUpdate dhcp-lease-comment.wifiwave2;
For legacy CAPsMAN:
$ScriptInstallUpdate dhcp-lease-comment.capsman;

View file

@ -1,6 +1,13 @@
Create DNS records for DHCP leases
==================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Automatically upgrade firmware and reboot
=========================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Download, import and update firewall address-lists
==================================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base
@ -56,8 +63,12 @@ available in my repository and downloaded automatically. Import it manually
(menu `/certificate/`) if missing.
Create firewall rules to process the packets that are related to addresses
from address-lists. This rejects the packets from and to ip addresses listed
in address-list `block`.
from address-lists.
### IPv4 rules
This rejects the packets from and to IPv4 addresses listed in
address-list `block`.
/ip/firewall/filter/add chain=input src-address-list=block action=reject reject-with=icmp-admin-prohibited;
/ip/firewall/filter/add chain=forward src-address-list=block action=reject reject-with=icmp-admin-prohibited;
@ -85,6 +96,33 @@ Alternatively handle the packets in firewall's raw section if you prefer:
> ⚠️ **Warning**: Just again... The order of firewall rules is important. Make
> sure they actually take effect as expected!
### IPv6 rules
These are the same rules, but for IPv6.
Reject packets in address-list `block`:
/ipv6/firewall/filter/add chain=input src-address-list=block action=reject reject-with=icmp-admin-prohibited;
/ipv6/firewall/filter/add chain=forward src-address-list=block action=reject reject-with=icmp-admin-prohibited;
/ipv6/firewall/filter/add chain=forward dst-address-list=block action=reject reject-with=icmp-admin-prohibited;
/ipv6/firewall/filter/add chain=output dst-address-list=block action=reject reject-with=icmp-admin-prohibited;
Allow packets in address-list `allow`:
/ipv6/firewall/filter/add chain=input src-address-list=allow action=accept;
/ipv6/firewall/filter/add chain=forward src-address-list=allow action=accept;
/ipv6/firewall/filter/add chain=forward dst-address-list=allow action=accept;
/ipv6/firewall/filter/add chain=output dst-address-list=allow action=accept;
Drop packets in firewall's raw section:
/ipv6/firewall/raw/add chain=prerouting src-address-list=block action=drop;
/ipv6/firewall/raw/add chain=prerouting dst-address-list=block action=drop;
/ipv6/firewall/raw/add chain=output dst-address-list=block action=drop;
> ⚠️ **Warning**: Just again... The order of firewall rules is important. Make
> sure they actually take effect as expected!
---
[⬅️ Go back to main README](../README.md)
[⬆️ Go back to top](#top)

View file

@ -1,6 +1,13 @@
Wait for global functions and modules
=====================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Send GPS position to server
===========================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Use WPA network with hotspot credentials
========================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base
@ -20,21 +27,15 @@ You need a properly configured hotspot on one (open) SSID and a WPA enabled
SSID with suffix "`-wpa`".
Then install the script.
Depending on whether you use `wifi` package (`/interface/wifi`), `wifiwave2`
package (`/interface/wifiwave2`) or legacy wifi with CAPsMAN (`/caps-man`)
you need to install a different script and set it as `on-login` script in
hotspot.
Depending on whether you use `wifi` package (`/interface/wifi`)or legacy
wifi with CAPsMAN (`/caps-man`) you need to install a different script and
set it as `on-login` script in hotspot.
For `wifi` (RouterOS 7.13 and later):
For `wifi`:
$ScriptInstallUpdate hotspot-to-wpa.wifi;
/ip/hotspot/user/profile/set on-login="hotspot-to-wpa.wifi" [ find ];
For `wifiwave2` (up to RouterOS 7.12):
$ScriptInstallUpdate hotspot-to-wpa.wifiwave2;
/ip/hotspot/user/profile/set on-login="hotspot-to-wpa.wifiwave2" [ find ];
For legacy CAPsMAN:
$ScriptInstallUpdate hotspot-to-wpa.capsman;
@ -46,16 +47,11 @@ With just `hotspot-to-wpa` installed the mac addresses will last in the
access list forever. Install the optional script for automatic cleanup
and add a scheduler.
For `wifi` (RouterOS 7.13 and later):
For `wifi`:
$ScriptInstallUpdate hotspot-to-wpa-cleanup.wifi,lease-script;
/system/scheduler/add interval=1d name=hotspot-to-wpa-cleanup on-event="/system/script/run hotspot-to-wpa-cleanup.wifi;" start-time=startup;
For `wifiwave2` (up to RouterOS 7.12):
$ScriptInstallUpdate hotspot-to-wpa-cleanup.wifiwave2,lease-script;
/system/scheduler/add interval=1d name=hotspot-to-wpa-cleanup on-event="/system/script/run hotspot-to-wpa-cleanup.wifiwave2;" start-time=startup;
For legacy CAPsMAN:
$ScriptInstallUpdate hotspot-to-wpa-cleanup.capsman,lease-script;
@ -97,15 +93,11 @@ Additionally templates can be created to give more options for access list:
* `vlan-id`: connect device to specific VLAN
* `vlan-mode`: set the VLAN mode for device
For a hotspot called `example` the template could look like this. For
`wifi` (RouterOS 7.13 and later):
For a hotspot called `example` the template could look like this.
For `wifi`:
/interface/wifi/access-list/add comment="hotspot-to-wpa template example" disabled=yes passphrase="ignore" ssid-regexp="^example\$" vlan-id=10;
For `wifiwave2` (up to RouterOS 7.12):
/interface/wifiwave2/access-list/add comment="hotspot-to-wpa template example" disabled=yes passphrase="ignore" ssid-regexp="^example\$" vlan-id=10;
For legacy CAPsMAN:
/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;

View file

@ -1,6 +1,13 @@
Manage IP addresses with bridge status
======================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
Description

View file

@ -1,6 +1,13 @@
Create DNS records for IPSec peers
==================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Update configuration on IPv6 prefix change
==========================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Run other scripts on DHCP lease
===============================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Manage LEDs dark mode
=====================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
Description

View file

@ -1,6 +1,13 @@
Forward log messages via notification
=====================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Manage ports in bridge
======================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../../README.md)
> **Info**: This module can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Manage VLANs on bridge ports
============================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../../README.md)
> **Info**: This module can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Inspect variables
=================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../../README.md)
> **Info**: This module can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
IP address calculation
======================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../../README.md)
> **Info**: This module can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Send notifications via e-mail
=============================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../../README.md)
> **Info**: This module can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Send notifications via Matrix
=============================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../../README.md)
> **Info**: This module can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Send notifications via Ntfy
===========================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../../README.md)
> **Info**: This module can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Send notifications via Telegram
===============================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../../README.md)
> **Info**: This module can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Download script and run it once
===============================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../../README.md)
> **Info**: This module can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Import ssh keys for public key authentication
=============================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../../README.md)
> **Info**: This module can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Mode button with multiple presses
=================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Manage DNS and DoH servers from netwatch
========================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Notify on host up and down
==========================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base
@ -83,9 +90,9 @@ with a resolvable name:
/tool/netwatch/add comment="notify, name=example.com, resolve=example.com";
But be warned: Dynamic updates will probably cause issues if the name has
more than one record in dns - a high rate of configuration changes (and flash
writes) at least.
This supports multiple A or AAAA records for a name just fine, even a CNAME
to those. An update happens only if no more record with the configured host
address is found.
### No notification on host down

View file

@ -1,6 +1,13 @@
Visualize OSPF state via LEDs
=============================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Manage system update
====================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.13-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Run scripts on ppp connection
=============================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Act on received SMS
===================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Forward received SMS
====================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Play Super Mario theme
======================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
Description

View file

@ -1,6 +1,13 @@
Chat with your router and send commands via Telegram bot
========================================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base
@ -100,6 +107,14 @@ scripting capabilities. Try to print what you want to act on...
/ip/address/remove [ find where interface=eth ];
What does work is using the persistent ids:
/ip/address/print show-ids;
The output contains an id starting with asterisk that can be used:
/ip/address/remove *E;
### Mind command runtime
The command is run in background while the script waits for it - about

View file

@ -1,6 +1,13 @@
Install LTE firmware upgrade
============================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
Description

View file

@ -1,6 +1,13 @@
Update GRE configuration with dynamic addresses
===============================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -1,6 +1,13 @@
Update tunnelbroker configuration
=================================
[![GitHub stars](https://img.shields.io/github/stars/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=red)](https://github.com/eworm-de/routeros-scripts/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=green)](https://github.com/eworm-de/routeros-scripts/network)
[![GitHub watchers](https://img.shields.io/github/watchers/eworm-de/routeros-scripts?logo=GitHub&style=flat&color=blue)](https://github.com/eworm-de/routeros-scripts/watchers)
[![required RouterOS version](https://img.shields.io/badge/RouterOS-7.12-yellow?style=flat)](https://mikrotik.com/download/changelogs/)
[![Telegram group @routeros_scripts](https://img.shields.io/badge/Telegram-%40routeros__scripts-%2326A5E4?logo=telegram&style=flat)](https://t.me/routeros_scripts)
[![donate with PayPal](https://img.shields.io/badge/Like_it%3F-Donate!-orange?logo=githubsponsors&logoColor=orange&style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A4ZXBD6YS2W8J)
[⬅️ Go back to main README](../README.md)
> **Info**: This script can not be used on its own but requires the base

View file

@ -8,40 +8,47 @@
# install firmware upgrade, and reboot
# https://git.eworm.de/cgit/routeros-scripts/about/doc/firmware-upgrade-reboot.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global LogPrintExit2;
:global ScriptLock;
:global VersionToNum;
:do {
:local ScriptName [ :jobname ];
$ScriptLock $0;
:global LogPrint;
:global ScriptLock;
:global VersionToNum;
:local RouterBoard [ /system/routerboard/get ];
:if ($RouterBoard->"current-firmware" = $RouterBoard->"upgrade-firmware") do={
$LogPrintExit2 info $0 ("Current and upgrade firmware match with version " . \
$RouterBoard->"current-firmware" . ".") true;
}
:if ([ $VersionToNum ($RouterBoard->"current-firmware") ] > [ $VersionToNum ($RouterBoard->"upgrade-firmware") ]) do={
$LogPrintExit2 info $0 ("Different firmware version is available, but it is a downgrade. Ignoring.") true;
}
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
:if ([ /system/routerboard/settings/get auto-upgrade ] = false) do={
$LogPrintExit2 info $0 ("Firmware version " . $RouterBoard->"upgrade-firmware" . \
" is available, upgrading.") false;
/system/routerboard/upgrade;
}
:local RouterBoard [ /system/routerboard/get ];
:if ($RouterBoard->"current-firmware" = $RouterBoard->"upgrade-firmware") do={
$LogPrint info $ScriptName ("Current and upgrade firmware match with version " . \
$RouterBoard->"current-firmware" . ".");
:error true;
}
:if ([ $VersionToNum ($RouterBoard->"current-firmware") ] > [ $VersionToNum ($RouterBoard->"upgrade-firmware") ]) do={
$LogPrint info $ScriptName ("Different firmware version is available, but it is a downgrade. Ignoring.");
:error true;
}
:while ([ :len [ /log/find where topics=({"system";"info";"critical"}) \
message="Firmware upgraded successfully, please reboot for changes to take effect!" ] ] = 0) do={
:delay 1s;
}
:if ([ /system/routerboard/settings/get auto-upgrade ] = false) do={
$LogPrint info $ScriptName ("Firmware version " . $RouterBoard->"upgrade-firmware" . \
" is available, upgrading.");
/system/routerboard/upgrade;
}
:local Uptime [ /system/resource/get uptime ];
:if ($Uptime < 1m) do={
:delay $Uptime;
}
:while ([ :len [ /log/find where topics=({"system";"info";"critical"}) \
message="Firmware upgraded successfully, please reboot for changes to take effect!" ] ] = 0) do={
:delay 1s;
}
$LogPrintExit2 info $0 ("Firmware upgrade successful, rebooting.") false;
/system/reboot;
:local Uptime [ /system/resource/get uptime ];
:if ($Uptime < 1m) do={
:delay $Uptime;
}
$LogPrint info $ScriptName ("Firmware upgrade successful, rebooting.");
/system/reboot;
} on-error={ }

View file

@ -8,115 +8,152 @@
# download, import and update firewall address-lists
# https://git.eworm.de/cgit/routeros-scripts/about/doc/fw-addr-lists.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global FetchUserAgent;
:global FwAddrLists;
:global FwAddrListTimeOut;
:do {
:local ScriptName [ :jobname ];
:global CertificateAvailable;
:global EitherOr;
:global LogPrintExit2;
:global LogPrintOnce;
:global ScriptLock;
:global WaitFullyConnected;
:global FetchUserAgent;
:global FwAddrLists;
:global FwAddrListTimeOut;
:local FindDelim do={
:local ValidChars "0123456789./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-";
:for I from=0 to=[ :len $1 ] do={
:if ([ :typeof [ :find $ValidChars [ :pick ($1 . " ") $I ] ] ] != "num") do={
:return $I;
:global CertificateAvailable;
:global EitherOr;
:global LogPrint;
:global LogPrintOnce;
:global ScriptLock;
:global WaitFullyConnected;
:local FindDelim do={
:local ValidChars "0123456789.:/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-";
:for I from=0 to=[ :len $1 ] do={
:if ([ :typeof [ :find $ValidChars [ :pick ($1 . " ") $I ] ] ] != "num") do={
:return $I;
}
}
}
}
$ScriptLock $0;
$WaitFullyConnected;
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
$WaitFullyConnected;
:local ListComment ("managed by " . $0);
:local ListComment ("managed by " . $ScriptName);
:foreach FwListName,FwList in=$FwAddrLists do={
:local Addresses ({});
:local CntAdd 0;
:local CntRenew 0;
:local CntRemove 0;
:local Failure false;
:foreach FwListName,FwList in=$FwAddrLists do={
:local CntAdd 0;
:local CntRenew 0;
:local CntRemove 0;
:local IPv4Addresses ({});
:local IPv6Addresses ({});
:local Failure false;
:foreach List in=$FwList do={
:local CheckCertificate "no";
:local Data false;
:local TimeOut [ $EitherOr [ :totime ($List->"timeout") ] $FwAddrListTimeOut ];
:foreach List in=$FwList do={
:local CheckCertificate "no";
:local Data false;
:local TimeOut [ $EitherOr [ :totime ($List->"timeout") ] $FwAddrListTimeOut ];
:if ([ :len ($List->"cert") ] > 0) do={
:set CheckCertificate "yes-without-crl";
:if ([ $CertificateAvailable ($List->"cert") ] = false) do={
$LogPrintExit2 warning $0 ("Downloading required certificate failed, trying anyway.") false;
:if ([ :len ($List->"cert") ] > 0) do={
:set CheckCertificate "yes-without-crl";
:if ([ $CertificateAvailable ($List->"cert") ] = false) do={
$LogPrint warning $ScriptName ("Downloading required certificate failed, trying anyway.");
}
}
:for I from=1 to=4 do={
:if ($Data = false) do={
:do {
:set Data ([ /tool/fetch check-certificate=$CheckCertificate output=user \
http-header-field=({ $FetchUserAgent }) ($List->"url") as-value ]->"data");
} on-error={
:if ($I < 4) do={
$LogPrint debug $ScriptName ("Failed downloading, " . $I . ". try: " . $List->"url");
:delay (($I * $I) . "s");
}
}
}
}
:if ($Data = false) do={
:set Data "";
:set Failure true;
$LogPrint warning $ScriptName ("Failed downloading list from: " . $List->"url");
}
:if ([ :len $Data ] > 63000) do={
$LogPrintOnce warning $ScriptName ("The list is huge and may be truncated: " . $List->"url");
}
:while ([ :len $Data ] != 0) do={
:local Line [ :pick $Data 0 [ :find $Data "\n" ] ];
:local Address ([ :pick $Line 0 [ $FindDelim $Line ] ] . ($List->"cidr"));
:if ($Address ~ "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}(/[0-9]{1,2})?\$" || \
$Address ~ "^[\\.a-zA-Z0-9-]+\\.[a-zA-Z]{2,}\$") do={
:set ($IPv4Addresses->$Address) $TimeOut;
}
:if ($Address ~ "^[0-9a-zA-Z]*:[0-9a-zA-Z:\\.]+(/[0-9]{1,3})?\$" || \
$Address ~ "^[\\.a-zA-Z0-9-]+\\.[a-zA-Z]{2,}\$") do={
:set ($IPv6Addresses->$Address) $TimeOut;
}
:set Data [ :pick $Data ([ :len $Line ] + 1) [ :len $Data ] ];
}
}
:for I from=1 to=4 do={
:if ($Data = false) do={
:do {
:set Data ([ /tool/fetch check-certificate=$CheckCertificate output=user \
http-header-field=({ $FetchUserAgent }) ($List->"url") as-value ]->"data");
} on-error={
:if ($I < 4) do={
$LogPrintExit2 debug $0 ("Failed downloading, " . $I . ". try: " . $List->"url") false;
:delay (($I * $I) . "s");
}
:foreach Entry in=[ /ip/firewall/address-list/find where list=$FwListName comment=$ListComment ] do={
:local Address [ /ip/firewall/address-list/get $Entry address ];
:if ([ :typeof ($IPv4Addresses->$Address) ] = "time") do={
$LogPrint debug $ScriptName ("Renewing IPv4 address for " . ($IPv4Addresses->$Address) . ": " . $Address);
/ip/firewall/address-list/set $Entry timeout=($IPv4Addresses->$Address);
:set ($IPv4Addresses->$Address);
:set CntRenew ($CntRenew + 1);
} else={
:if ($Failure = false) do={
$LogPrint debug $ScriptName ("Removing IPv4 address: " . $Address);
/ip/firewall/address-list/remove $Entry;
:set CntRemove ($CntRemove + 1);
}
}
}
:if ($Data = false) do={
:set Data "";
:set Failure true;
$LogPrintExit2 warning $0 ("Failed downloading list from: " . $List->"url") false;
}
:if ([ :len $Data ] > 63000) do={
$LogPrintOnce warning $0 ("The list is huge and may be truncated: " . $List->"url") false;
}
:while ([ :len $Data ] != 0) do={
:local Line [ :pick $Data 0 [ :find $Data "\n" ] ];
:local Address ([ :pick $Line 0 [ $FindDelim $Line ] ] . ($List->"cidr"));
:if ($Address ~ "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}(/[0-9]{1,2})?\$" || \
$Address ~ "^[\\.a-zA-Z0-9-]+\\.[a-zA-Z]{2,}\$") do={
:set ($Addresses->$Address) $TimeOut;
}
:set Data [ :pick $Data ([ :len $Line ] + 1) [ :len $Data ] ];
}
}
:foreach Entry in=[ /ip/firewall/address-list/find where list=$FwListName comment=$ListComment ] do={
:local Address [ /ip/firewall/address-list/get $Entry address ];
:if ([ :typeof ($Addresses->$Address) ] = "time") do={
$LogPrintExit2 debug $0 ("Renewing for " . ($Addresses->$Address) . ": " . $Address) false;
/ip/firewall/address-list/set $Entry timeout=($Addresses->$Address);
:set ($Addresses->$Address);
:set CntRenew ($CntRenew + 1);
} else={
:if ($Failure = false) do={
$LogPrintExit2 debug $0 ("Removing: " . $Address) false;
/ip/firewall/address-list/remove $Entry;
:set CntRemove ($CntRemove + 1);
:foreach Entry in=[ /ipv6/firewall/address-list/find where list=$FwListName comment=$ListComment ] do={
:local Address [ /ipv6/firewall/address-list/get $Entry address ];
:if ([ :typeof ($IPv6Addresses->$Address) ] = "time") do={
$LogPrint debug $ScriptName ("Renewing IPv6 address for " . ($IPv6Addresses->$Address) . ": " . $Address);
/ipv6/firewall/address-list/set $Entry timeout=($IPv6Addresses->$Address);
:set ($IPv6Addresses->$Address);
:set CntRenew ($CntRenew + 1);
} else={
:if ($Failure = false) do={
$LogPrint debug $ScriptName ("Removing: " . $Address);
/ipv6/firewall/address-list/remove $Entry;
:set CntRemove ($CntRemove + 1);
}
}
}
}
:foreach Address,Ignore in=$Addresses do={
$LogPrintExit2 debug $0 ("Adding for " . ($Addresses->$Address) . ": " . $Address) false;
:do {
/ip/firewall/address-list/add list=$FwListName comment=$ListComment address=$Address timeout=($Addresses->$Address);
:set ($Addresses->$Address);
:set CntAdd ($CntAdd + 1);
} on-error={
$LogPrintExit2 warning $0 ("Failed to add address " . $Address . " to list '" . $FwListName . "'.") false;
:foreach Address,Timeout in=$IPv4Addresses do={
$LogPrint debug $ScriptName ("Adding IPv4 address for " . $Timeout . ": " . $Address);
:do {
/ip/firewall/address-list/add list=$FwListName comment=$ListComment address=$Address timeout=$Timeout;
:set ($IPv4Addresses->$Address);
:set CntAdd ($CntAdd + 1);
} on-error={
$LogPrint warning $ScriptName ("Failed to add IPv4 address " . $Address . " to list '" . $FwListName . "'.");
}
}
}
$LogPrintExit2 info $0 ("list: " . $FwListName . " -- added: " . $CntAdd . " - renewed: " . $CntRenew . " - removed: " . $CntRemove) false;
}
:foreach Address,Timeout in=$IPv6Addresses do={
$LogPrint debug $ScriptName ("Adding IPv6 address for " . $Timeout . ": " . $Address);
:do {
/ipv6/firewall/address-list/add list=$FwListName comment=$ListComment address=$Address timeout=$Timeout;
:set ($IPv6Addresses->$Address);
:set CntAdd ($CntAdd + 1);
} on-error={
$LogPrint warning $ScriptName ("Failed to add IPv6 address " . $Address . " to list '" . $FwListName . "'.");
}
}
$LogPrint info $ScriptName ("list: " . $FwListName . " -- added: " . $CntAdd . " - renewed: " . $CntRenew . " - removed: " . $CntRemove);
}
} on-error={ }

View file

@ -243,10 +243,14 @@
"cert2-cn"="4n0th3r-s3cr3t";
};
# load custom settings from overlay
# load custom settings from overlay and snippets
# Warning: Do *NOT* copy this code to overlay!
:do {
/system/script/run global-config-overlay;
} on-error={
:log error ("Loading configuration from overlay failed!");
:foreach Script in=([ /system/script/find where name="global-config-overlay" ], \
[ /system/script/find where name~"^global-config-overlay.d/" ]) do={
:do {
/system/script/run $Script;
} on-error={
:log error ("Loading configuration from overlay or snippet " . \
[ /system/script/get $Script name ] . " failed!");
}
}

View file

@ -9,14 +9,19 @@
# global functions
# https://git.eworm.de/cgit/routeros-scripts/about/
:local 0 [ :jobname ];
:local ScriptName [ :jobname ];
# expected configuration version
:global ExpectedConfigVersion 118;
:global ExpectedConfigVersion 123;
# global variables not to be changed by user
:global GlobalFunctionsReady false;
:global FetchUserAgent ("User-Agent: Mikrotik/" . [ /system/resource/get version ] . " Fetch");
:global FetchUserAgent;
{
:local Resource [ /system/resource/get ];
:set FetchUserAgent ("User-Agent: Mikrotik/" . $Resource->"version" . \
" " . $Resource->"architecture-name" . " Fetch");
}
:global Identity [ /system/identity/get name ];
# global functions
@ -48,6 +53,7 @@
:global IsFullyConnected;
:global IsMacLocallyAdministered;
:global IsTimeSync;
:global LogPrint;
:global LogPrintExit2;
:global LogPrintOnce;
:global MAX;
@ -96,18 +102,18 @@
:local CommonName [ :tostr $1 ];
:global CertificateDownload;
:global LogPrintExit2;
:global LogPrint;
:global ParseKeyValueStore;
:if ([ /system/resource/get free-hdd-space ] < 8388608 && \
[ /certificate/settings/get crl-download ] = true && \
[ /certificate/settings/get crl-store ] = "system") do={
$LogPrintExit2 warning $0 ("This system has low free flash space but " . \
"is configured to download certificate CRLs to system!") false;
$LogPrint warning $0 ("This system has low free flash space but " . \
"is configured to download certificate CRLs to system!");
}
:if ([ :len [ /certificate/find where common-name=$CommonName ] ] = 0) do={
$LogPrintExit2 info $0 ("Certificate with CommonName \"" . $CommonName . "\" not available.") false;
$LogPrint info $0 ("Certificate with CommonName \"" . $CommonName . "\" not available.");
:if ([ $CertificateDownload $CommonName ] = false) do={
:return false;
}
@ -116,8 +122,8 @@
:local CertVal [ /certificate/get [ find where common-name=$CommonName ] ];
:while (($CertVal->"akid") != "" && ($CertVal->"akid") != ($CertVal->"skid")) do={
:if ([ :len [ /certificate/find where skid=($CertVal->"akid") ] ] = 0) do={
$LogPrintExit2 info $0 ("Certificate chain for \"" . $CommonName . \
"\" is incomplete, missing \"" . ([ $ParseKeyValueStore ($CertVal->"issuer") ]->"CN") . "\".") false;
$LogPrint info $0 ("Certificate chain for \"" . $CommonName . \
"\" is incomplete, missing \"" . ([ $ParseKeyValueStore ($CertVal->"issuer") ]->"CN") . "\".");
:if ([ $CertificateDownload $CommonName ] = false) do={
:return false;
}
@ -136,12 +142,12 @@
:global ScriptUpdatesUrlSuffix;
:global CertificateNameByCN;
:global LogPrintExit2;
:global LogPrint;
:global UrlEncode;
:global WaitForFile;
$LogPrintExit2 info $0 ("Downloading and importing certificate with " . \
"CommonName \"" . $CommonName . "\".") false;
$LogPrint info $0 ("Downloading and importing certificate with " . \
"CommonName \"" . $CommonName . "\".");
:do {
:local LocalFileName ($CommonName . ".pem");
:local UrlFileName ([ $UrlEncode $CommonName ] . ".pem");
@ -157,8 +163,7 @@
$CertificateNameByCN [ /certificate/get $Cert common-name ];
}
} on-error={
$LogPrintExit2 warning $0 ("Failed importing certificate with " . \
"CommonName \"" . $CommonName . "\"!") false;
$LogPrint warning $0 ("Failed importing certificate with CommonName \"" . $CommonName . "\"!");
:return false;
}
:return true;
@ -303,7 +308,7 @@
:global CertificateAvailable;
:global CleanFilePath;
:global LogPrintExit2;
:global LogPrint;
:global MkDir;
:global WaitForFile;
@ -318,22 +323,23 @@
:local PkgDest [ $CleanFilePath ($PkgDir . "/" . $PkgFile) ];
:if ([ $MkDir $PkgDir ] = false) do={
$LogPrintExit2 warning $0 ("Failed creating directory, not downloading package.") false;
$LogPrint warning $0 ("Failed creating directory, not downloading package.");
:return false;
}
:if ([ :len [ /file/find where name=$PkgDest type="package" ] ] > 0) do={
$LogPrintExit2 info $0 ("Package file " . $PkgName . " already exists.") false;
$LogPrint info $0 ("Package file " . $PkgName . " already exists.");
:return true;
}
:if ([ $CertificateAvailable "R3" ] = false) do={
$LogPrintExit2 error $0 ("Downloading required certificate failed.") true;
$LogPrint error $0 ("Downloading required certificate failed.");
:return false;
}
:local Url ("https://upgrade.mikrotik.com/routeros/" . $PkgVer . "/" . $PkgFile);
$LogPrintExit2 info $0 ("Downloading package file '" . $PkgName . "'...") false;
$LogPrintExit2 debug $0 ("... from url: " . $Url) false;
$LogPrint info $0 ("Downloading package file '" . $PkgName . "'...");
$LogPrint debug $0 ("... from url: " . $Url);
:local Retry 3;
:while ($Retry > 0) do={
:do {
@ -344,14 +350,14 @@
:return true;
}
} on-error={
$LogPrintExit2 debug $0 ("Downloading package file failed.") false;
$LogPrint debug $0 ("Downloading package file failed.");
}
/file/remove [ find where name=$PkgDest ];
:set Retry ($Retry - 1);
}
$LogPrintExit2 warning $0 ("Downloading package file '" . $PkgName . "' failed.") false;
$LogPrint warning $0 ("Downloading package file '" . $PkgName . "' failed.");
:return false;
}
@ -437,7 +443,7 @@
:global CertificateAvailable;
:global IsMacLocallyAdministered;
:global LogPrintExit2;
:global LogPrint;
:if ([ $IsMacLocallyAdministered $Mac ] = true) do={
:return "locally administered";
@ -445,7 +451,8 @@
:do {
:if ([ $CertificateAvailable "GTS CA 1P5" ] = false) do={
$LogPrintExit2 warning $0 ("Downloading required certificate failed.") true;
$LogPrint warning $0 ("Downloading required certificate failed.");
:error false;
}
:local Vendor ([ /tool/fetch check-certificate=yes-without-crl \
("https://api.macvendors.com/" . [ :pick $Mac 0 8 ]) output=user as-value ]->"data");
@ -454,9 +461,9 @@
:do {
/tool/fetch check-certificate=yes-without-crl ("https://api.macvendors.com/") \
output=none as-value;
$LogPrintExit2 debug $0 ("The mac vendor is not known in database.") false;
$LogPrint debug $0 ("The mac vendor is not known in database.");
} on-error={
$LogPrintExit2 warning $0 ("Failed getting mac vendor.") false;
$LogPrint warning $0 ("Failed getting mac vendor.");
}
:return "unknown vendor";
}
@ -603,7 +610,7 @@
:global IsTimeSyncCached;
:global IsTimeSyncResetNtp;
:global LogPrintExit2;
:global LogPrint;
:if ($IsTimeSyncCached = true) do={
:return true;
@ -632,7 +639,7 @@
:if ([ /system/license/get ]->"level" = "free" || \
[ /system/resource/get ]->"board-name" = "x86") do={
$LogPrintExit2 debug $0 ("No ntp client configured, relying on RTC for CHR free license and x86.") false;
$LogPrint debug $0 ("No ntp client configured, relying on RTC for CHR free license and x86.");
:return true;
}
@ -644,16 +651,15 @@
:return false;
}
$LogPrintExit2 debug $0 ("No time source configured! Returning gracefully...") false;
$LogPrint debug $0 ("No time source configured! Returning gracefully...");
:return true;
}
# log and print with same text, optionally exit
:set LogPrintExit2 do={
# log and print with same text
:set LogPrint do={
:local Severity [ :tostr $1 ];
:local Name [ :tostr $2 ];
:local Message [ :tostr $3 ];
:local Exit [ :tostr $4 ];
:global PrintDebug;
:global PrintDebugOverride;
@ -686,6 +692,19 @@
:if ($Severity != "debug" || $Debug = true) do={
:put ([ $PrintSeverity $Severity ] . ": " . $Message);
}
}
# log and print with same text, optionally exit
# Deprectated! - TODO: remove later
:set LogPrintExit2 do={
:local Severity [ :tostr $1 ];
:local Name [ :tostr $2 ];
:local Message [ :tostr $3 ];
:local Exit [ :tostr $4 ];
:global LogPrint;
$LogPrint $1 $2 $3;
:if ($Exit = "true") do={
:error ("Hard error to exit.");
@ -697,9 +716,8 @@
:local Severity [ :tostr $1 ];
:local Name [ :tostr $2 ];
:local Message [ :tostr $3 ];
:local Exit [ :tostr $4 ];
:global LogPrintExit2;
:global LogPrint;
:global LogPrintOnceMessages;
@ -712,7 +730,7 @@
}
:set ($LogPrintOnceMessages->$Message) 1;
$LogPrintExit2 $Severity $Name $Message $Exit;
$LogPrint $Severity $Name $Message;
}
# get max value
@ -732,24 +750,24 @@
:local Path [ :tostr $1 ];
:global CleanFilePath;
:global LogPrintExit2;
:global LogPrint;
:global WaitForFile;
:local MkTmpfs do={
:global LogPrintExit2;
:global LogPrint;
:global WaitForFile;
:if ([ :len [ /disk/find where slot=tmpfs type=tmpfs ] ] = 1) do={
:return true;
}
$LogPrintExit2 info $0 ("Creating disk of type tmpfs.") false;
$LogPrint info $0 ("Creating disk of type tmpfs.");
/file/remove [ find where name="tmpfs" type="directory" ];
:do {
/disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource/get total-memory ] / 3);
$WaitForFile "tmpfs";
} on-error={
$LogPrintExit2 warning $0 ("Creating disk of type tmpfs failed!") false;
$LogPrint warning $0 ("Creating disk of type tmpfs failed!");
:return false;
}
:return true;
@ -777,7 +795,7 @@
$WaitForFile $File;
/file/remove $File;
} on-error={
$LogPrintExit2 warning $0 ("Making directory '" . $Path . "' failed!") false;
$LogPrint warning $0 ("Making directory '" . $Path . "' failed!");
:return false;
}
@ -908,18 +926,18 @@
:local Warn [ :tostr $3 ];
:global IfThenElse;
:global LogPrintExit2;
:global LogPrint;
:global VersionToNum;
:if (!($Required ~ "^\\d+\\.\\d+((alpha|beta|rc|\\.)\\d+|)\$")) do={
$LogPrintExit2 error $0 ("No valid RouterOS version: " . $Required) false;
$LogPrint error $0 ("No valid RouterOS version: " . $Required);
:return false;
}
:if ([ $VersionToNum $Required ] > [ $VersionToNum [ /system/package/update/get installed-version ] ]) do={
:if ($Warn = "true") do={
$LogPrintExit2 warning $0 ("This " . [ $IfThenElse ([ :pick $Caller 0 ] = ("\$")) "function" "script" ] . \
" '" . $Caller . "' (at least specific functionality) requires RouterOS " . $Required . ". Please update!") false;
$LogPrint warning $0 ("This " . [ $IfThenElse ([ :pick $Caller 0 ] = ("\$")) "function" "script" ] . \
" '" . $Caller . "' (at least specific functionality) requires RouterOS " . $Required . ". Please update!");
}
:return false;
}
@ -930,7 +948,7 @@
:set ScriptFromTerminal do={
:local Script [ :tostr $1 ];
:global LogPrintExit2;
:global LogPrint;
:foreach Job in=[ /system/script/job/find where script=$Script ] do={
:set Job [ /system/script/job/get $Job ];
@ -938,11 +956,11 @@
:set Job [ /system/script/job/get [ find where .id=($Job->"parent") ] ];
}
:if (($Job->"type") = "login") do={
$LogPrintExit2 debug $0 ("Script " . $Script . " started from terminal.") false;
$LogPrint debug $0 ("Script " . $Script . " started from terminal.");
:return true;
}
}
$LogPrintExit2 debug $0 ("Script " . $Script . " NOT started from terminal.") false;
$LogPrint debug $0 ("Script " . $Script . " NOT started from terminal.");
:return false;
}
@ -964,7 +982,7 @@
:global EitherOr;
:global Grep;
:global IfThenElse;
:global LogPrintExit2;
:global LogPrint;
:global LogPrintOnce;
:global ParseKeyValueStore;
:global RequiredRouterOS;
@ -973,12 +991,12 @@
:global ValidateSyntax;
:if ([ $CertificateAvailable "E1" ] = false) do={
$LogPrintExit2 warning $0 ("Downloading certificate failed, trying without.") false;
$LogPrint warning $0 ("Downloading certificate failed, trying without.");
}
:foreach Script in=$Scripts do={
:if ([ :len [ /system/script/find where name=$Script ] ] = 0) do={
$LogPrintExit2 info $0 ("Adding new script: " . $Script) false;
$LogPrint info $0 ("Adding new script: " . $Script);
/system/script/add name=$Script owner=$Script source="#!rsc by RouterOS\n" comment=$NewComment;
}
}
@ -995,8 +1013,8 @@
:foreach Scheduler in=[ /system/scheduler/find where on-event~("\\b" . $ScriptVal->"name" . "\\b") ] do={
:local SchedulerVal [ /system/scheduler/get $Scheduler ];
:if ($ScriptVal->"policy" != $SchedulerVal->"policy") do={
$LogPrintExit2 warning $0 ("Policies differ for script '" . $ScriptVal->"name" . \
"' and its scheduler '" . $SchedulerVal->"name" . "'!") false;
$LogPrint warning $0 ("Policies differ for script '" . $ScriptVal->"name" . \
"' and its scheduler '" . $SchedulerVal->"name" . "'!");
}
}
@ -1005,7 +1023,7 @@
:local BaseUrl [ $EitherOr ($ScriptInfo->"base-url") $ScriptUpdatesBaseUrl ];
:local UrlSuffix [ $EitherOr ($ScriptInfo->"url-suffix") $ScriptUpdatesUrlSuffix ];
:local Url ($BaseUrl . $ScriptVal->"name" . ".rsc" . $UrlSuffix);
$LogPrintExit2 debug $0 ("Fetching script '" . $ScriptVal->"name" . "' from url: " . $Url) false;
$LogPrint debug $0 ("Fetching script '" . $ScriptVal->"name" . "' from url: " . $Url);
:local Result [ /tool/fetch check-certificate=yes-without-crl \
http-header-field=({ $FetchUserAgent }) $Url output=user as-value ];
:if ($Result->"status" = "finished") do={
@ -1013,11 +1031,11 @@
}
} on-error={
:if ($ScriptVal->"source" = "#!rsc by RouterOS\n") do={
$LogPrintExit2 warning $0 ("Failed fetching script '" . $ScriptVal->"name" . \
"', removing dummy. Typo on installation?") false;
$LogPrint warning $0 ("Failed fetching script '" . $ScriptVal->"name" . \
"', removing dummy. Typo on installation?");
/system/script/remove $Script;
} else={
$LogPrintExit2 warning $0 ("Failed fetching script '" . $ScriptVal->"name" . "'!") false;
$LogPrint warning $0 ("Failed fetching script '" . $ScriptVal->"name" . "'!");
}
}
}
@ -1028,7 +1046,7 @@
:local Required ([ $ParseKeyValueStore [ $Grep $SourceNew ("\23 requires RouterOS, ") ] ]->"version");
:if ([ $RequiredRouterOS $0 [ $EitherOr $Required "0.0" ] false ] = true) do={
:if ([ $ValidateSyntax $SourceNew ] = true) do={
$LogPrintExit2 info $0 ("Updating script: " . $ScriptVal->"name") false;
$LogPrint info $0 ("Updating script: " . $ScriptVal->"name");
/system/script/set owner=($ScriptVal->"name") source=$SourceNew $Script;
:if ($ScriptVal->"name" = "global-config") do={
:set ReloadGlobalConfig true;
@ -1037,48 +1055,48 @@
:set ReloadGlobalFunctions true;
}
} else={
$LogPrintExit2 warning $0 ("Syntax validation for script '" . $ScriptVal->"name" . \
"' failed! Ignoring!") false;
$LogPrint warning $0 ("Syntax validation for script '" . $ScriptVal->"name" . \
"' failed! Ignoring!");
}
} else={
$LogPrintOnce warning $0 ("The script '" . $ScriptVal->"name" . "' requires RouterOS " . \
$Required . ", which is not met by your installation. Ignoring!") false;
$Required . ", which is not met by your installation. Ignoring!");
}
} else={
$LogPrintExit2 warning $0 ("Looks like new script '" . $ScriptVal->"name" . \
"' is not valid (missing shebang). Ignoring!") false;
$LogPrint warning $0 ("Looks like new script '" . $ScriptVal->"name" . \
"' is not valid (missing shebang). Ignoring!");
}
} else={
$LogPrintExit2 debug $0 ("Script '" . $ScriptVal->"name" . "' did not change.") false;
$LogPrint debug $0 ("Script '" . $ScriptVal->"name" . "' did not change.");
}
} else={
$LogPrintExit2 debug $0 ("No update for script '" . $ScriptVal->"name" . "'.") false;
$LogPrint debug $0 ("No update for script '" . $ScriptVal->"name" . "'.");
}
}
:if ($ReloadGlobalFunctions = true) do={
$LogPrintExit2 info $0 ("Reloading global functions.") false;
$LogPrint info $0 ("Reloading global functions.");
:do {
/system/script/run global-functions;
} on-error={
$LogPrintExit2 error $0 ("Reloading global functions failed!") false;
$LogPrint error $0 ("Reloading global functions failed!");
}
}
:if ($ReloadGlobalConfig = true) do={
$LogPrintExit2 info $0 ("Reloading global configuration.") false;
$LogPrint info $0 ("Reloading global configuration.");
:do {
/system/script/run global-config;
} on-error={
$LogPrintExit2 error $0 ("Reloading global configuration failed!" . \
" Syntax error or missing overlay?") false;
$LogPrint error $0 ("Reloading global configuration failed!" . \
" Syntax error or missing overlay?");
}
}
:if ($ExpectedConfigVersionBefore > $ExpectedConfigVersion) do={
$LogPrintExit2 warning $0 ("The configuration version decreased from " . \
$LogPrint warning $0 ("The configuration version decreased from " . \
$ExpectedConfigVersionBefore . " to " . $ExpectedConfigVersion . \
". Installed an older version?") false;
". Installed an older version?");
}
:if ($ExpectedConfigVersionBefore < $ExpectedConfigVersion) do={
@ -1088,14 +1106,14 @@
:do {
:local Url ($ScriptUpdatesBaseUrl . "news-and-changes.rsc" . $ScriptUpdatesUrlSuffix);
$LogPrintExit2 debug $0 ("Fetching news, changes and migration: " . $Url) false;
$LogPrint debug $0 ("Fetching news, changes and migration: " . $Url);
:local Result [ /tool/fetch check-certificate=yes-without-crl \
http-header-field=({ $FetchUserAgent }) $Url output=user as-value ];
:if ($Result->"status" = "finished") do={
:set ChangeLogCode ($Result->"data");
}
} on-error={
$LogPrintExit2 warning $0 ("Failed fetching news, changes and migration!") false;
$LogPrint warning $0 ("Failed fetching news, changes and migration!");
}
:if ([ :len $ChangeLogCode ] > 0) do={
@ -1103,10 +1121,10 @@
:do {
[ :parse $ChangeLogCode ];
} on-error={
$LogPrintExit2 warning $0 ("The changelog failed to run!") false;
$LogPrint warning $0 ("The changelog failed to run!");
}
} else={
$LogPrintExit2 warning $0 ("The changelog failed syntax validation!") false;
$LogPrint warning $0 ("The changelog failed syntax validation!");
}
}
@ -1115,14 +1133,14 @@
:local Migration ($GlobalConfigMigration->[ :tostr $I ]);
:if ([ :typeof $Migration ] = "str") do={
:if ([ $ValidateSyntax $Migration ] = true) do={
$LogPrintExit2 info $0 ("Applying migration for change " . $I . ": " . $Migration) false;
$LogPrint info $0 ("Applying migration for change " . $I . ": " . $Migration);
:do {
[ :parse $Migration ];
} on-error={
$LogPrintExit2 warning $0 ("Migration code for change " . $I . " failed to run!") false;
$LogPrint warning $0 ("Migration code for change " . $I . " failed to run!");
}
} else={
$LogPrintExit2 warning $0 ("Migration code for change " . $I . " failed syntax validation!") false;
$LogPrint warning $0 ("Migration code for change " . $I . " failed syntax validation!");
}
}
}
@ -1131,7 +1149,7 @@
:local NotificationMessage ("The configuration version on " . $Identity . " increased " . \
"to " . $ExpectedConfigVersion . ", current configuration may need modification. " . \
"Please review and update global-config-overlay, then re-run global-config.");
$LogPrintExit2 info $0 ($NotificationMessage) false;
$LogPrint info $0 ($NotificationMessage);
:if ([ :len $GlobalConfigChanges ] > 0) do={
:set NotificationMessage ($NotificationMessage . "\n\nChanges:");
@ -1139,7 +1157,7 @@
:local Change ($GlobalConfigChanges->[ :tostr $I ]);
:set NotificationMessage ($NotificationMessage . "\n " . \
[ $SymbolForNotification "pushpin" "*" ] . $Change);
$LogPrintExit2 info $0 ("Change " . $I . ": " . $Change) false;
$LogPrint info $0 ("Change " . $I . ": " . $Change);
}
} else={
:set NotificationMessage ($NotificationMessage . "\n\nNews and changes are not available.");
@ -1169,12 +1187,11 @@
# lock script against multiple invocation
:set ScriptLock do={
:local Script [ :tostr $1 ];
:local DoReturn $2;
:local WaitMax ([ :tonum $3 ] * 10);
:local WaitMax ([ :tonum $3 ] * 10);
:global GetRandom20CharAlNum;
:global IfThenElse;
:global LogPrintExit2;
:global LogPrint;
:global ScriptLockOrder;
:if ([ :typeof $ScriptLockOrder ] = "nothing") do={
@ -1260,15 +1277,17 @@
}
:if ([ :len [ /system/script/find where name=$Script ] ] = 0) do={
$LogPrintExit2 error $0 ("A script named '" . $Script . "' does not exist!") true;
$LogPrint error $0 ("A script named '" . $Script . "' does not exist!");
:error false;
}
:if ([ $JobCount $Script ] = 0) do={
$LogPrintExit2 error $0 ("No script '" . $Script . "' is running!") true;
$LogPrint error $0 ("No script '" . $Script . "' is running!");
:error false;
}
:if ([ $TicketCount $Script ] >= [ $JobCount $Script ]) do={
$LogPrintExit2 error $0 ("More tickets than running scripts '" . $Script . "', resetting!") false;
$LogPrint error $0 ("More tickets than running scripts '" . $Script . "', resetting!");
:set ($ScriptLockOrder->$Script) ({});
/system/script/job/remove [ find where script=$Script ];
}
@ -1285,13 +1304,13 @@
:if ([ $IsFirstTicket $Script $MyTicket ] = true && [ $TicketCount $Script ] = [ $JobCount $Script ]) do={
$RemoveTicket $Script $MyTicket;
$CleanupTickets $Script;
:return false;
:return true;
}
$RemoveTicket $Script $MyTicket;
$LogPrintExit2 info $0 ("Script '" . $Script . "' started more than once" . [ $IfThenElse ($WaitCount > 0) \
" and timed out waiting for lock" "" ] . "... Aborting.") [ $IfThenElse ($DoReturn = true) false true ];
:return true;
$LogPrint info $0 ("Script '" . $Script . "' started more than once" . [ $IfThenElse ($WaitCount > 0) \
" and timed out waiting for lock" "" ] . "...");
:return false;
}
# send notification via NotificationFunctions - expects at least two string arguments
@ -1354,7 +1373,7 @@
}
:if ([ :len ($Symbols->$Name) ] = 0) do={
$LogPrintOnce warning $0 ("No symbol available for name '" . $Name . "'!") false;
$LogPrintOnce warning $0 ("No symbol available for name '" . $Name . "'!");
:return "";
}
@ -1525,17 +1544,17 @@
:do {
/system/script/run $Script;
} on-error={
$LogPrintExit2 error $0 ("Module '" . $ScriptVal->"name" . "' failed to run.") false;
$LogPrint error $0 ("Module '" . $ScriptVal->"name" . "' failed to run.");
}
} else={
$LogPrintExit2 error $0 ("Module '" . $ScriptVal->"name" . "' failed syntax validation, skipping.") false;
$LogPrint error $0 ("Module '" . $ScriptVal->"name" . "' failed syntax validation, skipping.");
}
}
# Log success
:local Resource [ /system/resource/get ];
$LogPrintOnce info $0 ("Loaded on " . $Resource->"board-name" . \
" with RouterOS " . $Resource->"version" . ".") false;
$LogPrintOnce info $ScriptName ("Loaded on " . $Resource->"board-name" . \
" with RouterOS " . $Resource->"version" . ".");
# signal we are ready
:set GlobalFunctionsReady true;

View file

@ -8,6 +8,5 @@
# wait for global-functions to finish
# https://git.eworm.de/cgit/routeros-scripts/about/doc/global-wait.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }

View file

@ -8,38 +8,43 @@
# track gps data by sending json data to http server
# https://git.eworm.de/cgit/routeros-scripts/about/doc/gps-track.md
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global GpsTrackUrl;
:global Identity;
:do {
:local ScriptName [ :jobname ];
:global LogPrintExit2;
:global ScriptLock;
:global WaitFullyConnected;
:global GpsTrackUrl;
:global Identity;
$ScriptLock $0;
$WaitFullyConnected;
:global LogPrint;
:global ScriptLock;
:global WaitFullyConnected;
:local CoordinateFormat [ /system/gps/get coordinate-format ];
:local Gps [ /system/gps/monitor once as-value ];
:if ($Gps->"valid" = true) do={
:do {
/tool/fetch check-certificate=yes-without-crl $GpsTrackUrl output=none \
http-method=post http-header-field=({ "Content-Type: application/json" }) \
http-data=("{" . \
"\"lat\":\"" . ($Gps->"latitude") . "\"," . \
"\"lon\":\"" . ($Gps->"longitude") . "\"," . \
"\"identity\":\"" . $Identity . "\"" . \
"}") as-value;
$LogPrintExit2 debug $0 ("Sending GPS data in " . $CoordinateFormat . " format: " . \
"lat: " . ($Gps->"latitude") . " " . \
"lon: " . ($Gps->"longitude")) false;
} on-error={
$LogPrintExit2 warning $0 ("Failed sending GPS data!") false;
:if ([ $ScriptLock $ScriptName ] = false) do={
:error false;
}
} else={
$LogPrintExit2 debug $0 ("GPS data not valid.") false;
}
$WaitFullyConnected;
:local CoordinateFormat [ /system/gps/get coordinate-format ];
:local Gps [ /system/gps/monitor once as-value ];
:if ($Gps->"valid" = true) do={
:do {
/tool/fetch check-certificate=yes-without-crl $GpsTrackUrl output=none \
http-method=post http-header-field=({ "Content-Type: application/json" }) \
http-data=("{" . \
"\"lat\":\"" . ($Gps->"latitude") . "\"," . \
"\"lon\":\"" . ($Gps->"longitude") . "\"," . \
"\"identity\":\"" . $Identity . "\"" . \
"}") as-value;
$LogPrint debug $ScriptName ("Sending GPS data in " . $CoordinateFormat . " format: " . \
"lat: " . ($Gps->"latitude") . " " . \
"lon: " . ($Gps->"longitude"));
} on-error={
$LogPrint warning $ScriptName ("Failed sending GPS data!");
}
} else={
$LogPrint debug $ScriptName ("GPS data not valid.");
}
} on-error={ }

View file

@ -11,59 +11,64 @@
#
# !! Do not edit this file, it is generated from template!
:local 0 [ :jobname ];
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global EitherOr;
:global LogPrintExit2;
:global ParseKeyValueStore;
:global ScriptLock;
:do {
:local ScriptName [ :jobname ];
$ScriptLock $0 false 10;
:global EitherOr;
:global LogPrint;
:global ParseKeyValueStore;
:global ScriptLock;
:local DHCPServers ({});
:foreach Server in=[ /ip/dhcp-server/find where comment~"hotspot-to-wpa" ] do={
:local ServerVal [ /ip/dhcp-server/get $Server ]
:local ServerInfo [ $ParseKeyValueStore ($ServerVal->"comment") ];
:if (($ServerInfo->"hotspot-to-wpa") = "wpa") do={
:set ($DHCPServers->($ServerVal->"name")) \
[ :totime [ $EitherOr ($ServerInfo->"timeout") 4w ] ];
:if ([ $ScriptLock $ScriptName 10 ] = false) do={
:error false;
}
}
:foreach Client in=[ /caps-man/registration-table/find where comment~"^hotspot-to-wpa:" ] do={
:local ClientVal [ /caps-man/registration-table/get $Client ];
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic \
mac-address=($ClientVal->"mac-address") ] do={
:if (($DHCPServers->[ /ip/dhcp-server/lease/get $Lease server ]) > 0s) do={
$LogPrintExit2 info $0 ("Client with mac address " . ($ClientVal->"mac-address") . \
" connected to WPA, making lease static.") false;
/ip/dhcp-server/lease/make-static $Lease;
/ip/dhcp-server/lease/set comment=($ClientVal->"comment") $Lease;
:local DHCPServers ({});
:foreach Server in=[ /ip/dhcp-server/find where comment~"hotspot-to-wpa" ] do={
:local ServerVal [ /ip/dhcp-server/get $Server ]
:local ServerInfo [ $ParseKeyValueStore ($ServerVal->"comment") ];
:if (($ServerInfo->"hotspot-to-wpa") = "wpa") do={
:set ($DHCPServers->($ServerVal->"name")) \
[ :totime [ $EitherOr ($ServerInfo->"timeout") 4w ] ];
}
}
}
:foreach Client in=[ /caps-man/access-list/find where comment~"^hotspot-to-wpa:" \
!(comment~[ /system/clock/get date ]) ] do={
:local ClientVal [ /caps-man/access-list/get $Client ];
:if ([ :len [ /ip/dhcp-server/lease/find where !dynamic comment~"^hotspot-to-wpa:" \
mac-address=($ClientVal->"mac-address") ] ] = 0) do={
$LogPrintExit2 info $0 ("Client with mac address " . ($ClientVal->"mac-address") . \
" did not connect to WPA, removing from access list.") false;
/caps-man/access-list/remove $Client;
:foreach Client in=[ /caps-man/registration-table/find where comment~"^hotspot-to-wpa:" ] do={
:local ClientVal [ /caps-man/registration-table/get $Client ];
:foreach Lease in=[ /ip/dhcp-server/lease/find where dynamic \
mac-address=($ClientVal->"mac-address") ] do={
:if (($DHCPServers->[ /ip/dhcp-server/lease/get $Lease server ]) > 0s) do={
$LogPrint info $ScriptName ("Client with mac address " . ($ClientVal->"mac-address") . \
" connected to WPA, making lease static.");
/ip/dhcp-server/lease/make-static $Lease;
/ip/dhcp-server/lease/set comment=($ClientVal->"comment") $Lease;
}
}
}
}
:foreach Server,Timeout in=$DHCPServers do={
:foreach Lease in=[ /ip/dhcp-server/lease/find where !dynamic status="waiting" \
server=$Server last-seen>$Timeout comment~"^hotspot-to-wpa:" ] do={
:local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
$LogPrintExit2 info $0 ("Client with mac address " . ($LeaseVal->"mac-address") . \
" was not seen for " . ($LeaseVal->"last-seen") . ", removing.") false;
/caps-man/access-list/remove [ find where comment~"^hotspot-to-wpa:" \
mac-address=($LeaseVal->"mac-address") ];
/ip/dhcp-server/lease/remove $Lease;
:foreach Client in=[ /caps-man/access-list/find where comment~"^hotspot-to-wpa:" \
!(comment~[ /system/clock/get date ]) ] do={
:local ClientVal [ /caps-man/access-list/get $Client ];
:if ([ :len [ /ip/dhcp-server/lease/find where !dynamic comment~"^hotspot-to-wpa:" \
mac-address=($ClientVal->"mac-address") ] ] = 0) do={
$LogPrint info $ScriptName ("Client with mac address " . ($ClientVal->"mac-address") . \
" did not connect to WPA, removing from access list.");
/caps-man/access-list/remove $Client;
}
}
}
:foreach Server,Timeout in=$DHCPServers do={
:foreach Lease in=[ /ip/dhcp-server/lease/find where !dynamic status="waiting" \
server=$Server last-seen>$Timeout comment~"^hotspot-to-wpa:" ] do={
:local LeaseVal [ /ip/dhcp-server/lease/get $Lease ];
$LogPrint info $ScriptName ("Client with mac address " . ($LeaseVal->"mac-address") . \
" was not seen for " . ($LeaseVal->"last-seen") . ", removing.");
/caps-man/access-list/remove [ find where comment~"^hotspot-to-wpa:" \
mac-address=($LeaseVal->"mac-address") ];
/ip/dhcp-server/lease/remove $Lease;
}
}
} on-error={ }

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